Skip to content

faq004_dynamic page display

Johannes Brachem edited this page Apr 29, 2019 · 1 revision

How can I dynamically control the display of whole pages?

There are two major ways to do this:

  1. Use a filter function and a simple switch at the end of Section 4
  2. Define a custom class with a switch in the method onHidingWidget()

Feel free to use the option that seems more straightforward to you.

1) Using a filter function

Download minimal example: script.py

In Section 2 of your script.py, you can define filter functions that return True or False. These functions allow you to toggle the display of question groups at the end of Section 4 using the command questionGroup.setShouldBeShownFilterFunction(function), where questionGroup is a placeholder for the name of your question group and function is a placeholder for the name of your function.

In the example below, the display of Page 2 is toggled depending on the answer to the question p1_mc on Page 1. We define two filter functions: One that returns True of the answer is "1" and False otherwise, and one that returns True when the answer is "2" and False otherwise.

This is what your Section 2 would look like:

#################################################
### Section 2: Global variables and functions ###
#################################################

expName='Alfred Beispiel'
expVersion='0.01'

def filter_condition1(experiment):
    cond_condition=experiment.dataManager.findExperimentDataByUid('page1')['p1_mc']
    if cond_condition == 1:
        return True
    else:
        return False

def filter_condition2(experiment):
    cond_condition=experiment.dataManager.findExperimentDataByUid('page1')['p1_mc']
    if cond_condition == 2:
        return True
    else:
        return False

Section 3 is empty in this example, as we don't need to define a new custom class. This is what Section 4 would look like in this example:

########################################
### Section 4: Experiment generation ###
########################################

class Script(object):
    def generate_experiment(self):
        exp=Experiment('web', expName, expVersion)

        # Define Page 1
        p1=CompositeQuestion(title=u"Hello World", uid=u"page1")
        p1_text=TextElement("This is a minimal example.")
        p1_mc=SingleChoiceElement(u"Pick one option.",
                                    itemLabels=["Option 1", "Option 2"],
                                    name="p1_mc",
                                    forceInput=True)

        p1.addElements(p1_text, p1_mc)

        # Define Question Group for Page 1
        startQG=SegmentedQG()
        startQG.appendItems(p1)


        # Define Page 2
        p2=CompositeQuestion(title=u"Page 2")
        p2_text=TextElement("You chose option 1.")
        p2.addElements(p2_text)

        # Define Page 3
        p3=CompositeQuestion(title=u"Page 3")
        p3_text=TextElement(
            "This is page 3. If you see this right after the Hello World page, you chose option 2. Page 2 is not displayed in this condition.")
        p3.addElements(p3_text)

        # Define Two Question Groups, one containing both Pages 2 and 3, one containing only Page 3.
        mainQGa=SegmentedQG()
        mainQGa.appendItems(p2, p3)

        mainQGb=SegmentedQG()
        mainQGb.appendItems(p3)

        # Use filter functions
        mainQGa.setShouldBeShownFilterFunction(filter_condition1)  # If filter_condition1 is True, mainQGa will be shown
        mainQGb.setShouldBeShownFilterFunction(filter_condition2)  # If filter_condition2 is True, mainQGb will be shown

        # --- EXPERIMENT CONTROLS --- #
        # ------------------------------------------------------------------- #

        # All Question Groups are added here
        exp.questionController.appendItems(startQG, mainQGa, mainQGb)

        return exp


generate_experiment=Script().generate_experiment

2) Using a custom class with onHidingWidget

Download minimal example: script.py

You can define a custom class in Section 3 that works as a switch. The trick is to define the method onHidingWidget, which contains code that gets run when the page is closed. Depending on previous answers, you can use this method to append customized compositions of the rest of the experiment. This flowchart illustrates the process:

Custom Class Flowchart

This is what the Sections 3 and 4 of your scipt.py would look like when you use this solution.

#################################
### Section 3: Custom classes ###
#################################

class StartQuestion(CompositeQuestion):

    # Define dynamic actions on closing of the page
    def onHidingWidget(self):

        mainQG=SegmentedQG()  # Define an empty segmented question group

        # Extract data from Page 1, Element p1_mc
        # Note that Page 1 is defined below in Section 4 using the StartQuestion class defined here
        condition=self._experiment.dataManager.findExperimentDataByUid('page1')['p1_mc']

        # Define Page 2
        p2=CompositeQuestion(title=u"Page 2")
        p2_text=TextElement("You chose option 1.")
        p2.addElements(p2_text)

        # Define Page 3
        p3=CompositeQuestion(title=u"Page 3")
        p3_text=TextElement("This is page 3. If you see this right after the Hello World page, you chose option 2. Page 2 is not displayed in this condition.")
        p3.addElements(p3_text)

        # If condition is "1", append both Page 2 and 3 to the mainQG question group
        if condition == 1:
            mainQG.appendItems(p2, p3)

        # If condition is "2", append only Page 3 to the mainQG question group
        if condition == 2:
            mainQG.appendItems(p3)

        # Add the mainQG question group to the running experiment
        self._experiment.questionController.appendItems(mainQG)




########################################
### Section 4: Experiment generation ###
########################################

class Script(object):
    def generate_experiment(self):
        exp=Experiment('web', expName, expVersion)

        # --- PAGE 1 --- #
        # Use the StartQuestion class defined above in Section 3 to create a page
        p1=StartQuestion(title=u"Hello World", uid="page1")

        # Define and add elements to the page as usual
        p1_text=TextElement("This is a minimal example.")

        p1_mc=SingleChoiceElement(u"Pick one option.",
                                    itemLabels=["Option 1", "Option 2"],
                                    name="p1_mc",
                                    forceInput=True)    # forceInput needs to be true for Alfred to correctly display
                                                        # the "continue" button at the end of the page instead of
                                                        # "end".

        p1.addElements(p1_text, p1_mc)

        # Define a question group and add Page 1 to it
        start=SegmentedQG()
        start.appendItems(p1)

        # --- EXPERIMENT CONTROLS --- #
        # ------------------------------------------------------------------- #
        exp.questionController.appendItems(start)

        return exp


generate_experiment=Script().generate_experiment