Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    getPickListFilterCriteria not called on DynamicForm fetchData()

    I have been fighting a dependent combobox issue for a while. Everything seems to work during new item entry but the dependent combo query is not correct for a fetchData() call. The parent's key is not being used for the secondary combo query. I put together a small test of this issue as follows:

    Code:
    isc.DataSource.create({
      ID: "itemHeaderDS",
      dataFormat: "json",
      title: "Item",
      fields: [
        {
          name: "itemId",
          title: "Item ID",
          type: "text",
          primaryKey: true,
          required: true,
          length: 30
        },
        {
          name: "itemDesc",
          title: "Description",
          type: "text",
          required: true,
          length: 30
        },
        {
          name: "major",
          title: "Major",
          type: "text",
          required: true,
          length: 4,
          foreignKey: "majorValuesDS.major"
        },
        {
          name: "minor",
          title: "Minor",
          type: "text",
          required: true,
          length: 4,
          foreignKey: "minorValuesDS.minor"
        }
      ],
      clientOnly: true,
      testData: [
        { itemId: "143560", itemDesc: "A test item", major: "TOYO", minor: "M101"}
      ]
    })
    
    
    isc.RestDataSource.create({
      ID: "majorValuesDS",
      dataFormat: "json",
      title: "Majors",
      fields: [
        {
          name: "major",
          title: "Major",
          type: "text",
          primaryKey: true,
          canEdit: false,
          length: 4
        },
        {
          name: "description",
          title: "Description",
          type: "text",
          canEdit: false,
          length: 30
        }
      ],
      clientOnly: true,
      testData: [
        { major:"AS", description:"ARMSTRONG" },
        { major:"FS", description:"FIRESTONE" },
        { major:"TOYO", description:"TOYO" }
      ]
    })
    
    
    
    isc.DataSource.create({
      ID: "minorValuesDS",
      dataFormat: "json",
      dataURL: "/minors.json",
      title: "Minors",
      fields: [
        {
          name: "PK_minorValuesDS",
          title: "PrimaryKey",
          type: "text",
          primaryKey: true,
          length: 256,
          hidden: true
        },
        {
          name: "minor",
          title: "Minor",
          type: "text",
          canEdit: false,
          length: 4
        },
        {
          name: "major",
          title: "Major",
          type: "text",
          canEdit: false,
          length: 4
        },
        {
          name: "description",
          title: "Description",
          type: "text",
          canEdit: false,
          length: 30
        }
      ]
    })
    
    
    
    
    isc.DynamicForm.create({
        width: 500,
        numCols: 4,
        autoFocus: true,
        dataSource: "itemHeaderDS",
        fields: [
                    {name: "itemId"},
                    {name: "itemDesc"},
    
                    {name: "major", title: "Major", editorType: "ComboBoxItem", type: "select", width: "*",
                        optionDataSource:"majorValuesDS",
                        allowEmptyValue: true,
                        valueField:"major",
                        displayField:"description",
                        showPickListOnKeypress: true,
                        completeOnTab: true,
                        changed: function (form, item, value) {    
                            var field = form.getField('minor');
                            field.setValue(null);
                            field.setDisabled(!value);
                        },
                        pickListWidth:450,
                        pickListFields: [
                          { name:"major", width: 50 },
                          { name:"description" }
                        ] },
                    {name: "minor", title: "Minor", editorType: "ComboBoxItem", type: "select", width: "*",
                        optionDataSource:"minorValuesDS",
                        autoFetchData: false,
                        allowEmptyValue: true,
                        disabled: true,
                        valueField:"minor",
                        displayField:"description",
                        showPickListOnKeypress: true,
                        completeOnTab: true,
                        pickListWidth:450,
                        pickListFields: [
                          { name:"minor", width: 50 },
                          { name:"description" }
                        ],
                        getPickListFilterCriteria : function () {
                            isc.warn('getPickListFilterCriteria');
                            return {
                                major: this.form.getValue("major"),
                                minor: this.form.getValue("minor")
                            }
                        } },
                    {name: "editBtn", title: "Edit Existing Item", type: "button", click: "this.form.editItem(form)" },
                    {name: "newBtn", title: "New Item", type: "button", click: "this.form.editNewRecord()" }
    
        ],
                editItem : function (form) {
                    form.fetchData();
                            var field = form.getField('minor');
                            field.setDisabled(false);
                }
    
    });
    I separated the minorValuesDS DataSource data into a separate file (minors.json) so I could watch the query string using FireBug:

    Code:
    [
        { PK_minorValuesDS:"AS/RR1", major:"AS", minor:"RR1", description:"RADIAL1" },
        { PK_minorValuesDS:"AS/RR2", major:"AS", minor:"RR2", description:"RADIAL2" },
        { PK_minorValuesDS:"FS/LT", major:"FS", minor:"LT", description:"LIGHT TRUCK" },
        { PK_minorValuesDS:"FS/TRK", major:"FS", minor:"TRK", description:"TRUCK" },
        { PK_minorValuesDS:"TOYO/HT", major:"TOYO", minor:"HT", description:"HT" },
        { PK_minorValuesDS:"TOYO/M101", major:"TOYO", minor:"M101", description:"M101" }
    ]
    To test just press the Edit Existing Item button. According to FireBug, the query on minorValuesDS includes just the "minor" field value. If getPickListFilterCriteria was called an alert would be displayed and the "major" value would be included as well.

    Code:
    From FireBug:
    GET http://localhost:8080/minors.json?minor=M101 (22ms)
    To see the proper query, press New Item button, select a major and then select a minor:

    Code:
    GET http://localhost:8080/minors.json?major=FS (220ms)
    In this case we don't yet have a minor value to be part of the query but the major was included and the alert displayed.


    Is this a bug or am I missing something key?

    Thanks!

    #2
    Hi David

    By default when you call 'setValue()' on any form item with an option dataSource / display field, it will attempt to map the specified data value to the appropriate display value by performing a fetch against the option dataSource with the criteria set to
    {valueField:new data value}
    and displaying the displayField's value from the returned record.
    This behavior can be disabled by setting fetchMissingValues to false for the item.

    In addition to this ComboBoxItems and SelectItems have to fetch data from the option dataSource to display in the pickList. If autoFetchData is set to true, this fetch will happen when the item is first rendered out, otherwise it occurs when the drop down list is shown to the user.
    This fetch makes use of the specified pickListCriteria.

    These are 2 basically separate mechanisms, although if the data value has been picked up in the pickListMenu (the drop down list) for a comboBox / selectItem, it will be used as the display value for the item.

    So in your case you're seeing the first mechanism kick off the fetch in response to the 'setValue()' for the item that fires in response to your 'fetchData()' call on the form, and that's failing to pick up your custom pickListFilter criteria.
    However if you then click on the button to actually show the pickList, you'll see the options shown in the pickList should get retrieved via a fetch operation making use of your custom filter criteria.

    Let us know if this doesn't make sense, or if this behaviour isn't allowing you're app to behave as you intend.

    Thanks
    Isomorphic Software

    Comment


      #3
      Thanks so much for the reply. The problem with this behavior is that the display value will not be correct without making the query with the other value that I can provide with getPickListFilterCriteria. In other words, the minorValuesDS has two fields that combine to make a primary key. As the minor value is not unique to majors the display value may come from a completely unrelated major.

      The obvious other benefit to pulling the proper criteria during setValue is that the drop list is already correct if the user wants to make another selection.

      Is there a workaround so that I can have the proper criteria in the fetch for the display value when loading a record for editing?

      Comment


        #4
        Hi David
        A couple of options spring to mind.

        Setting fetchMissingValues to false, and then calling 'fetchData()' explicitly on the ComboBoxiItem would mean that you'd only perform the fetch against the pickList data (using those specified criteria), and when the set of results returned, if any of them matched the specified data value, the display value will be updated automatically

        Alternatively, you could explicitly perform a fetch against your dataSource with the appropriate criteria to pick up the display value you need, create an explicit valueMap from it, and apply it to the ComboBox via setValueMap(). Note that SmartClient does support items with both an explicit valueMap and an optionDataSource.

        Let us know if these won't do it for you

        Thanks
        Isomorphic Software

        Comment


          #5
          Isomorphic,

          Thanks for the workaround. Delaying the fetch of missing values does work. Is there a reason not to use the same mechanism for querying the option dataSource to locate the display value during SetValue as would be used when a user interacts with the combo manually? That is, why would getPickListFilterCriteria not be used? Is this just an optimization? It would seem logical to get the criteria from the get() method and add or replace the new data value in the criteria.

          Generally, I want to make an form edit of a record have the same state that the form had when the user first entered the data. As the workaround works, I can continue for the time being but please consider a change to the standard mechanism as describe above.

          Thanks!

          Comment

          Working...
          X