Tips for working with repeat YAML

The chances are highly likely for you to run into scenarios where there will be repetitive code in your solutions.

And althought we at Jigx are constantly looking at ways to make things easier for you, there’s already some tips and tricks you can use to elevate your development and save some time.

In this post I will be discussing three areas where slight improvements could save you a great deal of effort:

  • Using global vs local datasources
  • Using global actions for repetitive actions
  • Using expressions for repetitive conditional checks, etc.

Let’s get started, shall we?

1. Global vs Local Datasources
The first suggestion probably seems like a bit of a non-brainer, yet this one regularly makes an appearance. A good general rule-of-thumb is to use global datasources as much as possible unless you are unable to. This allows you to merely reference the table everywhere in your solution, but prevents you from having to define the datasource locally everywhere you use it.

Local datasources should be used only in instances where you want to pass in parameters for your query that are only available on a particular jig.

For example if you want to filter records on a list, the filter value is defined in that jig and so your query would happen on the jig itself.

2. Global Actions
More often-than-not, I’ve run into scenarios where the same actions are used in various places, often with just a tiny bit of a difference between them. You may find that setting up a global action to dynamically handle these differences may save you lots of time (and space) too.

Take this code for example, the actions are very similar and as a result can easily be moved over to a global action. Notice the code difference when you move them over to a global action using the action.execute-action . Commented out code is the previous actions and the current actions under onPress are where I’m reusing the same global action called expander-action:

        type: component.expander
        instanceId: process-info
        options:
          isInitiallyCollapsed: false
          header:
            centerElement: 
              type: component.titles
              options:
                title: =@ctx.current.item.question
                subtitle: |
                  =@ctx.components.chkYes.state.value = true ? 'Yes':
                    @ctx.components.chkNo.state.value = true ? 'No':
                    @ctx.components.chkNA.state.value = true ? "N/A": " " 
                icon: |
                  =@ctx.components.chkYes.state.value = true ? 'checkbox-checked':
                    @ctx.components.chkNo.state.value = true ? 'checkbox-checked':
                    @ctx.components.chkNA.state.value = true ? 'checkbox-checked':'checkbox-unchecked'
                iconColor: |
                  =@ctx.components.chkYes.state.value = true ? 'positive':
                    @ctx.components.chkNo.state.value = true ? 'negative':
                    @ctx.components.chkNA.state.value = true ? 'color3':'color14'
          children:
            - type: component.entity
              options:
                children:
                  - type: component.entity-field
                    options:
                      label: Question
                      value: =@ctx.current.item.question & '?'
            - type: component.entity
              options:
                children:
                  - type: component.entity-field
                    options:
                      label: Description
                      value: =@ctx.current.item.description
            - type: component.form
              options:
                isDiscardChangesAlertEnabled: false
                children:
                  - type: component.field-row
                    options:
                      children:
                        - type: component.checkbox
                          instanceId: chkYes
                          options:
                            isRequired: false
                            isOptionalLabelHidden: true
                            label: Yes
                            style:
                              isDisabled: =@ctx.components.chkYes.state.value
                            onPress:
                              type: action.execute-action
                              options:
                                action: expander-action
                                parameters:
                                  when: =@ctx.components.chkNo.state.value
                                  count: =@ctx.datasources.summaryCount.count - 1
                              
                              # type: action.action-list
                              # options:
                              #   actions:
                              #     - type: action.execute-entity
                              #       when: =@ctx.components.chkNo.state.value
                              #       options:
                              #         provider: DATA_PROVIDER_LOCAL
                              #         entity: summaryCount
                              #         method: save
                              #         goBack: stay
                              #         data:
                              #           id: ='CK/Process-' & @ctx.solution.state.summaryId
                              #           title: 
                              #           count: =$count(@ctx.datasources.summaryCount.count) - 1
                              #     - type: action.reset-state
                              #       options:
                              #         state: =@ctx.components.chkNo.state.value

                        - type: component.checkbox
                          instanceId: chkNo
                          options:
                            isRequired: false
                            isOptionalLabelHidden: true
                            label: No
                            style:
                              isDisabled: =@ctx.components.chkNo.state.value
                            onPress: 
                              type: action.execute-action
                              options:
                                action: expander-action
                                parameters:
                                  when: =@ctx.components.chkYes.state.value
                                  count: =$count(@ctx.datasources.summaryCount.count) < 1 ? 1:$number(@ctx.datasources.summaryCount.count) + 1
                                  reset: =@ctx.components.chkNA.state.value     

                              # type: action.action-list
                              # options: 
                              #   actions:
                              #     - type: action.execute-entity
                              #       when: =@ctx.components.chkYes.state.value
                              #       options:
                              #         provider: DATA_PROVIDER_LOCAL
                              #         entity: summaryCount
                              #         method: save
                              #         goBack: stay
                              #         data:
                              #           id: ='CK/Process-' & @ctx.solution.state.summaryId 
                              #           count: =$count(@ctx.datasources.summaryCount.count) < 1 ? 1:$number(@ctx.datasources.summaryCount.count) + 1
                              #     - type: action.reset-state
                              #       options:
                              #         state: =@ctx.components.chkYes.state.value
                              #     - type: action.reset-state
                              #       options:
                              #         state: =@ctx.components.chkNA.state.value
                                      
                        - type: component.checkbox
                          instanceId: chkNA
                          options:
                            isRequired: false
                            isOptionalLabelHidden: true
                            label: N/A
                            style:
                              isDisabled: =@ctx.components.chkNA.state.value
                            onPress: 
                              type: action.execute-action
                              options:
                                action: expander-action
                                parameters:
                                  when: =@ctx.components.chkYes.state.value
                                  count: =@ctx.datasources.summaryCount.count - 1
                                  reset: =@ctx.components.chkNA.state.value

Here is the action definition:

action: 
  type: action.action-list
  options:
    actions:
      - type: action.execute-entity
        when: =@ctx.action.parameters.when
        options:
          provider: DATA_PROVIDER_LOCAL
          entity: summaryCount
          method: save
          goBack: stay
          data:
            id: ='CK/Process-' & @ctx.solution.state.summaryId
            title: 
            count: =ctx.action.parameters.count
            
      - type: action.reset-state
        options:
          state: =@ctx.action.parameters.when
      - type: action.reset-state
        when: =@ctx.action.parameters.reset != null
        options:
          state: =@ctx.action.parameters.reset

parameters:
  when:
    type: string
    required: true
  
  reset:
    type: string
    required: false
  
  count:
    type: number
    required: true

Other than re-usability, this provides you with only one place that you may need to update certain fields that need to be changed instead of having to change this in multiple places.

3. Expressions
Expressions are useful to break down complex queries or even aid as a tool to add reusability in a simple way. Expressions can be either local (set up in the jig) or global (set up in the index file).

Using the above example, I’d like to provide some examples for you of how expressions can be used to:
i.) Improve reusability
ii.) Improve code length by using shorthand instead of full expressions
iii.) Improve time spent when updates are required as you only need to manage that in the expressions and not everywhere the expressions are called.

Look at the below code as an example and compare it to the original code above.

Notice that the value of chkYes is now only managed in the expressions.
Should you need to update the instanceId of the component, you only need to update it one place.

Examples that rely on solution.state or other environmental or solution level variables are easy to set up in your global expressions.

        type: component.expander
        instanceId: process-info
        options:
          isInitiallyCollapsed: false
          header:
            centerElement: 
              type: component.titles
              options:
                title: =@ctx.current.item.question
                subtitle: |
                  =$chkYesValue ? 'Yes':
                    $chkNoValue = true ? 'No':
                    $chkNaValue = true ? "N/A": " " 
                icon: |
                  =$chkYesValue = true ? 'checkbox-checked':
                    $chkNoValue = true ? 'checkbox-checked':
                    $chkNaValue = true ? 'checkbox-checked':'checkbox-unchecked'
                iconColor: |
                  =$chkYesValue = true ? 'positive':
                    $chkNoValue = true ? 'negative':
                    $chkNaValue = true ? 'color3':'color14'
          children:
            - type: component.entity
              options:
                children:
                  - type: component.entity-field
                    options:
                      label: Question
                      value: =@ctx.current.item.question & '?'
            - type: component.entity
              options:
                children:
                  - type: component.entity-field
                    options:
                      label: Description
                      value: =@ctx.current.item.description
            - type: component.form
              options:
                isDiscardChangesAlertEnabled: false
                children:
                  - type: component.field-row
                    options:
                      children:
                        - type: component.checkbox
                          instanceId: chkYes
                          options:
                            isRequired: false
                            isOptionalLabelHidden: true
                            label: Yes
                            style:
                              isDisabled: =$chkYesValue
                            onPress:
                              type: action.execute-action
                              options:
                                action: expander-action
                                parameters:
                                  when: =$chkNoValue
                                  count: =$countDatasource - 1
                              
                        - type: component.checkbox
                          instanceId: chkNo
                          options:
                            isRequired: false
                            isOptionalLabelHidden: true
                            label: No
                            style:
                              isDisabled: =$chkNoValue
                            onPress: 
                              type: action.execute-action
                              options:
                                action: expander-action
                                parameters:
                                  when: =$chkYesValue
                                  count: =$countDatasource < 1 ? 1:$number$countDatasource) + 1
                                  reset: =$chkYesValue 

                        - type: component.checkbox
                          instanceId: chkNA
                          options:
                            isRequired: false
                            isOptionalLabelHidden: true
                            label: N/A
                            style:
                              isDisabled: =$chkNaValue
                            onPress: 
                              type: action.execute-action
                              options:
                                action: expander-action
                                parameters:
                                  when: =$chkYesValue
                                  count: =$countDatasource - 1
                                  reset: =$chkYesValue

expressions:
  # Can be referenced by full expression @ctx.expressions.{key} or using the shorthand ${key}
  chkNaValue: =@ctx.components.chkNA.state.value
  chkNoValue: =@ctx.components.chkNo.state.value
  chkYesValue: =@ctx.components.chkYes.state.value
  countDatasource: =@ctx.datasources.summaryCount.count
2 Likes