Dojo FilteringSelect仅触发OnChange事件一次

Dojo FilteringSelect仅触发OnChange事件一次

问题描述:

我在dojo.Dialog中有dojo.form.FilteringSelect小部件,它是以编程方式创建的。我将一个onChange事件连接到FilteringSelect,按照预期,我第一次选择和输入FilteringSelect。任何后续的时间我选择一些新的事件,onChange事件不会触发。Dojo FilteringSelect仅触发OnChange事件一次

我试过在为new FilteringSelect语句提供参数时声明onChange属性。我试过使用dojo.connect。我试过mySelectDijit.on。所有都有相同的效果。

var select = new dijit.form.FilteringSelect({ 
    id : "fields-select-" + expNum, 
    store : store, 
    required : false, 
    intermediateChanges : true 
}, fieldinput); 

dojo.connect(select, 'onChange', LoadOperatorValue); 

如何得到onChange触发事件,每次FilteringSelect变化?

UPDATE:

我已经添加了相关的代码。此代码基于ArcGIS Javascript API v3.3,其中包含Dojo。

dojo.require("dijit.Dialog"); 
dojo.require("dijit.form.FilteringSelect"); 
dojo.require("dojo.store.Memory"); 
dojo.require("dijit.form.MultiSelect"); 
dojo.require("dijit.form.TextBox"); 
dojo.require("dijit.form.Textarea"); 
dojo.require("dijit.form.NumberSpinner"); 
dojo.require("dijit.form.DateTextBox"); 

var expNum = 1; 
var queryDiv; 
var layer; 
var dialog; 

function CreateDialog(lyr) { 

    layer = lyr; 

    queryDiv = dojo.create("div", { 
     id : "queryDiv" 
    }); 

    var buttonInput = dojo.create("button", { 
     id : "button" 
    }, queryDiv); 

    var button = new dijit.form.Button({ 
     id : "addExpression", 
     label : "Add Expression", 
     onClick : function() { 
      BuildExpression(layer); 
     } 
    }, buttonInput); 

    BuildExpression(layer) 

    dialog = new dijit.Dialog({ 
     title : "Query: " + layer.layerObject.name, 
     content : queryDiv, 
     style : "width: 600px" 
    }); 

    dialog.show(); 
} 

function BuildExpression(layer) { 

    var expDiv = dojo.create("div", { 
     class : "expression", 
     id : "expression-" + expNum 
    }, queryDiv); 

    var filterDiv = dojo.create("div", { 
     class : "filter", 
     id : "filter-" + expNum 
    }, expDiv); 

    var fieldSpan = dojo.create("span", { 
     id : "field-" + expNum, 
     class : "field" 
    }, filterDiv); 

    var operatorSpan = dojo.create("span", { 
     id : "operator-" + expNum, 
     class : "operator" 
    }, filterDiv); 

    var valueSpan = dojo.create("span", { 
     id : "value-" + expNum, 
     class : "value" 
    }, filterDiv); 

    var removeSpan = dojo.create("span", { 
     id : "remove-" + expNum, 
     class : "remove" 
    }, filterDiv); 

    var removeInput = dojo.create("button", { 
     id : "button" 
    }, removeSpan); 

    var removeButton = new dijit.form.Button({ 
     id : "removeExpression" + expNum, 
     label : "Remove", 
     onClick : function() { 
      dojo.destroy(expDiv); 
     } 
    }, removeInput); 

    var fieldinput = dojo.create("input", { 
     id : "field-input-" + expNum 
    }, fieldSpan); 

    var fields = []; 
    dojo.forEach(layer.layerObject.fields, function(field, index) { 
     if (index < layer.layerObject.infoTemplate.info.fieldInfos.length && layer.layerObject.infoTemplate.info.fieldInfos[index].visible == true) { 
      field.operatorSpan = operatorSpan; 
      field.valueSpan = valueSpan; 
      fields.push({ 
       name : field.alias, 
       id : field 
      }); 
     } 
    }); 

    var store = new dojo.store.Memory({ 
     data : fields 
    }); 

    var select = new dijit.form.FilteringSelect({ 
     id : "fields-select-" + expNum, 
     store : store, 
     required : false, 
     intermediateChanges : true 
    }, fieldinput); 

    dojo.connect(select, 'onChange', LoadOperatorValue); 
    expNum++ 
} 

function LoadOperatorValue(field) { debugger; 
    dojo.empty(field.operatorSpan); 
    dojo.empty(field.valueSpan); 

    if ("domain" in field && "codedValues" in field.domain) { 

     field.operatorSpan.innerHTML = "IS"; 

     var sel = dojo.create("select", { 
      id : "multiselect-" + expNum 
     }, field.valueSpan); 

     dojo.forEach(field.domain.codedValues, function(cv, index) { 
      dojo.create("option", { 
       innerHTML : cv.name, 
       value : cv.code 
      }, sel); 
     }); 

     var multiselect = new dijit.form.MultiSelect({}, sel); 

    } else if (field.type == "esriFieldTypeString") { 

     var operatorInput = dojo.create("input", { 
      id : "operator-input" 
     }, field.operatorSpan); 

     var operators = [{ 
      name : "IS", 
      id : " = " 
     }, { 
      name : "IS NOT", 
      id : " <> " 
     }, { 
      name : "LIKE", 
      id : " LIKE " 
     }, { 
      name : "NOT LIKE", 
      id : " NOT LIKE " 
     }]; 

     var opStore = new dojo.store.Memory({ 
      data : operators 
     }); 

     var select = new dijit.form.FilteringSelect({ 
      id : "operator-select-" + expNum, 
      store : opStore, 
      required : false 
     }, operatorInput); 

     var valueInput = dojo.create("input", { 
      id : "value-input" 
     }, field.valueSpan); 

     if (field.length < 50) { 
      var textBox = new dijit.form.TextBox({ 
       id : "value-input-" + expNum 
      }, valueInput); 
     } else { 
      var textBox = new dijit.form.Textarea({ 
       id : "value-input-" + expNum 
      }, valueInput); 
     } 

    } else if (field.type == "esriFieldTypeDouble" || field.type == "esriFieldTypeSingle" || field.type == "esriFieldTypeInteger" || field.type == "esriFieldTypeSmallInteger") { 

     var operatorInput = dojo.create("input", { 
      id : "operator-input" 
     }, field.operatorSpan); 

     var operators = [{ 
      name : "=", 
      id : " = " 
     }, { 
      name : "!=", 
      id : " <> " 
     }, { 
      name : "<", 
      id : " < " 
     }, { 
      name : "<=", 
      id : " <= " 
     }, { 
      name : ">", 
      id : " > " 
     }, { 
      name : ">=", 
      id : " >= " 
     }]; 

     var opStore = new dojo.store.Memory({ 
      data : operators 
     }); 

     var select = new dijit.form.FilteringSelect({ 
      id : "operator-select-" + expNum, 
      store : opStore, 
      required : false 
     }, operatorInput); 

     var valueInput = dojo.create("input", { 
      id : "value-input" 
     }, field.valueSpan); 

     var constraints = {}; 

     if ("domain" in field && "range" in field.domain) { 
      constraints.min = field.domain.range.min; 
      constraints.max = field.domain.range.max; 
     } 

     if (field.type == "esriFieldTypeDouble" || field.type == "esriFieldTypeSingle") { 
      constraints.places = 2; 
     } 

     var numberSpinner = new dijit.form.NumberSpinner({ 
      id : "value-input-" + expNum 
     }, valueInput); 

    } else if (field.type == "esriFieldTypeDate") { 

     var operatorInput = dojo.create("input", { 
      id : "operator-input" 
     }, field.operatorSpan); 

     var operators = [{ 
      name : "IS", 
      id : " = " 
     }, { 
      name : "IS NOT", 
      id : " <> " 
     }, { 
      name : "Before", 
      id : " < " 
     }, { 
      name : "Before or IS", 
      id : " <= " 
     }, { 
      name : "After", 
      id : " > " 
     }, { 
      name : "After or IS", 
      id : " >= " 
     }]; 

     var opStore = new dojo.store.Memory({ 
      data : operators 
     }); 

     var select = new dijit.form.FilteringSelect({ 
      id : "operator-select-" + expNum, 
      store : opStore, 
      required : false 
     }, operatorInput); 

     var valueInput = dojo.create("input", { 
      id : "value-input" 
     }, field.valueSpan); 

     var dateTextBox = new dijit.form.DateTextBox({ 
      id : "value-input-" + expNum 
     }, valueInput); 

    } else { 

    } 
} 
+0

嗨,布赖恩,哪个版本的dojo在这里被使用? – Jeremy 2013-02-08 23:36:26

+0

@Jez - 根据ESRI ArcGIS Javascript API,它包含了dojo 1.8。 – Brian 2013-02-08 23:44:35

当我创建这些类型在过去的小部件嗯,我已经做了如下,它几乎和你的一样,但注意到在更改处理...

var select = new dijit.form.FilteringSelect({ 
    id : "fields-select-" + expNum, 
    store : store, 
    required : false, 
    onChange: function(value){ 
     //do something here 
    } 
}, fieldinput); 

更新:从重新阅读你的文章,我可以看到你已经尝试过这种方法,我只是想我会把它留在答案作为参考,因为它在过去为我工作。

UPDATE

关于dojo 1.8,它可能是值得使用dojo's templated widgets帮助消除了很多程序在你的JavaScript创建的元素的考虑。还值得通过一些其他dojo教程,如getting selective with dijit,custom widgetsdefining modules教程,他们将真正帮助您充分利用dojo小部件。 “越来越有选择性”有一个过滤选择小部件。

很难说出为什么你的onChange事件只被调度一次。我真的可以说的是,你完全简化了你刚刚过滤的选择部件的所有内容,并确保你可以单独捕获onChange事件多次。然后开始整合其余的代码。

对不起,我不能给你任何确切的答案,我会继续寻找。

UPDATE

好,我刚刚你的代码,并得到它使用Dojo 1.8在测试环境中运行,我不得不剥离出层对象,用一个简单的数组替换它,但它似乎工作好。我还使用define将代码更改为模块(在modules tutorial中进行了解释)。这里是代码...

define(["dijit/Dialog", 
     "dijit/form/FilteringSelect", 
     "dojo/store/Memory", 
     "dijit/form/MultiSelect", 
     "dijit/form/TextBox", 
     "dijit/form/Textarea", 
     "dijit/form/NumberSpinner", 
     "dijit/form/DateTextBox"], 

    function(){ 

     var expNum = 1; 
     var queryDiv; 
     var layer; 
     var dialog; 

     function BuildExpression(layer) { 

      var expDiv = dojo.create("div", { 
       class : "expression", 
       id : "expression-" + expNum 
      }, queryDiv); 

      var filterDiv = dojo.create("div", { 
       class : "filter", 
       id : "filter-" + expNum 
      }, expDiv); 

      var fieldSpan = dojo.create("span", { 
       id : "field-" + expNum, 
       class : "field" 
      }, filterDiv); 

      var operatorSpan = dojo.create("span", { 
       id : "operator-" + expNum, 
       class : "operator" 
      }, filterDiv); 

      var valueSpan = dojo.create("span", { 
       id : "value-" + expNum, 
       class : "value" 
      }, filterDiv); 

      var removeSpan = dojo.create("span", { 
       id : "remove-" + expNum, 
       class : "remove" 
      }, filterDiv); 

      var removeInput = dojo.create("button", { 
       id : "button" 
      }, removeSpan); 

      var removeButton = new dijit.form.Button({ 
       id : "removeExpression" + expNum, 
       label : "Remove", 
       onClick : function() { 
        dojo.destroy(expDiv); 
       } 
      }, removeInput); 

      var fieldinput = dojo.create("input", { 
       id : "field-input-" + expNum 
      }, fieldSpan); 

      var fields = [{"name":"value1", "id":"v1"}, {"name":"value2", "id":"v2"}]; 
      //dojo.forEach(layer.layerObject.fields, function(field, index) { 
      // if (index < layer.layerObject.infoTemplate.info.fieldInfos.length && layer.layerObject.infoTemplate.info.fieldInfos[index].visible == true) { 
      //  field.operatorSpan = operatorSpan; 
      //  field.valueSpan = valueSpan; 
      //  fields.push({ 
      //   name : field.alias, 
      //   id : field 
      //  }); 
      // } 
      // }); 

      var store = new dojo.store.Memory({ 
       data : fields 
      }); 

      var select = new dijit.form.FilteringSelect({ 
       id : "fields-select-" + expNum, 
       store : store, 
       required : false, 
       intermediateChanges : true 
      }, fieldinput); 

      dojo.connect(select, 'onChange', function(value){console.log(value)}); 
      expNum++ 
     } 

     function LoadOperatorValue(field) { debugger; 
      dojo.empty(field.operatorSpan); 
      dojo.empty(field.valueSpan); 

      if ("domain" in field && "codedValues" in field.domain) { 

       field.operatorSpan.innerHTML = "IS"; 

       var sel = dojo.create("select", { 
        id : "multiselect-" + expNum 
       }, field.valueSpan); 

       dojo.forEach(field.domain.codedValues, function(cv, index) { 
        dojo.create("option", { 
         innerHTML : cv.name, 
         value : cv.code 
        }, sel); 
       }); 

       var multiselect = new dijit.form.MultiSelect({}, sel); 

      } else if (field.type == "esriFieldTypeString") { 

       var operatorInput = dojo.create("input", { 
        id : "operator-input" 
       }, field.operatorSpan); 

       var operators = [{ 
        name : "IS", 
        id : " = " 
       }, { 
        name : "IS NOT", 
        id : " <> " 
       }, { 
        name : "LIKE", 
        id : " LIKE " 
       }, { 
        name : "NOT LIKE", 
        id : " NOT LIKE " 
       }]; 

       var opStore = new dojo.store.Memory({ 
        data : operators 
       }); 

       var select = new dijit.form.FilteringSelect({ 
        id : "operator-select-" + expNum, 
        store : opStore, 
        required : false 
       }, operatorInput); 

       var valueInput = dojo.create("input", { 
        id : "value-input" 
       }, field.valueSpan); 

       if (field.length < 50) { 
        var textBox = new dijit.form.TextBox({ 
         id : "value-input-" + expNum 
        }, valueInput); 
       } else { 
        var textBox = new dijit.form.Textarea({ 
         id : "value-input-" + expNum 
        }, valueInput); 
       } 

      } else if (field.type == "esriFieldTypeDouble" || field.type == "esriFieldTypeSingle" || field.type == "esriFieldTypeInteger" || field.type == "esriFieldTypeSmallInteger") { 

       var operatorInput = dojo.create("input", { 
        id : "operator-input" 
       }, field.operatorSpan); 

       var operators = [{ 
        name : "=", 
        id : " = " 
       }, { 
        name : "!=", 
        id : " <> " 
       }, { 
        name : "<", 
        id : " < " 
       }, { 
        name : "<=", 
        id : " <= " 
       }, { 
        name : ">", 
        id : " > " 
       }, { 
        name : ">=", 
        id : " >= " 
       }]; 

       var opStore = new dojo.store.Memory({ 
        data : operators 
       }); 

       var select = new dijit.form.FilteringSelect({ 
        id : "operator-select-" + expNum, 
        store : opStore, 
        required : false 
       }, operatorInput); 

       var valueInput = dojo.create("input", { 
        id : "value-input" 
       }, field.valueSpan); 

       var constraints = {}; 

       if ("domain" in field && "range" in field.domain) { 
        constraints.min = field.domain.range.min; 
        constraints.max = field.domain.range.max; 
       } 

       if (field.type == "esriFieldTypeDouble" || field.type == "esriFieldTypeSingle") { 
        constraints.places = 2; 
       } 

       var numberSpinner = new dijit.form.NumberSpinner({ 
        id : "value-input-" + expNum 
       }, valueInput); 

      } else if (field.type == "esriFieldTypeDate") { 

       var operatorInput = dojo.create("input", { 
        id : "operator-input" 
       }, field.operatorSpan); 

       var operators = [{ 
        name : "IS", 
        id : " = " 
       }, { 
        name : "IS NOT", 
        id : " <> " 
       }, { 
        name : "Before", 
        id : " < " 
       }, { 
        name : "Before or IS", 
        id : " <= " 
       }, { 
        name : "After", 
        id : " > " 
       }, { 
        name : "After or IS", 
        id : " >= " 
       }]; 

       var opStore = new dojo.store.Memory({ 
        data : operators 
       }); 

       var select = new dijit.form.FilteringSelect({ 
        id : "operator-select-" + expNum, 
        store : opStore, 
        required : false 
       }, operatorInput); 

       var valueInput = dojo.create("input", { 
        id : "value-input" 
       }, field.valueSpan); 

       var dateTextBox = new dijit.form.DateTextBox({ 
        id : "value-input-" + expNum 
       }, valueInput); 

      } else { 

      } 
     } 

     return { 
      CreateDialog: function(lyr) { 

       layer = lyr; 

       queryDiv = dojo.create("div", { 
        id : "queryDiv" 
       }); 

       var buttonInput = dojo.create("button", { 
        id : "button" 
       }, queryDiv); 

       var button = new dijit.form.Button({ 
        id : "addExpression", 
        label : "Add Expression", 
        onClick : function() { 
         BuildExpression(layer); 
        } 
       }, buttonInput); 

       BuildExpression(layer) 

       dialog = new dijit.Dialog({ 
        title : "Query: ",// + layer.layerObject.name, 
        content : queryDiv, 
        style : "width: 600px" 
       }); 

       dialog.show(); 
      } 
     } 
    } 
) 

然后,我通过要求模块在一个简单的html文件,并调用CreateDialog函数来测试它...

require(
    ["dojo/parser", 
    "tb/testModule", 
    "dojo/domReady!"], 

    function(parser, testModule){    
     parser.parse(); 
     //test module 
     testModule.CreateDialog({}); 
    } 
) 

注:包“TB/testModule”使用TB,因为这就是我在我的dojo config设置的包名。

如果您开始在已筛选的选择框中输入内容,只要您在数组中的两个值中的任何一个上获得自动填写,您应该会看到控制台中记录的等效值。

这里是我所得到的屏幕截图,你可以看到,我第一次登录值1的ID,则值2的id ...

enter image description here

如果你没有得到第二个事件,它必须在某个地方迷路。我想知道变量作用域是否会影响事物,但我不需要改变它们的任何范围。我只是将主函数移动到模块的返回块中。

+0

谢谢@Jez - 这是我最初尝试的,但它只在我第一次从下拉列表中选择一个值时才起作用。任何额外的时间没有发生。 – Brian 2013-02-08 22:08:46

+0

我刚刚检查了这段代码与我自己的一些工作,它确实有效,也许你可以添加一些额外的代码,我会仔细看看。 – Jeremy 2013-02-08 22:11:36

+0

我已经添加了我的其他javascript代码。一般来说,我对Dojo和Web开发还很陌生。我能够使它大致与JSFiddle一起工作,但我无法保存小提琴。我想知道是否有可能会干扰ArcGIS JavaScript API的其他内容? – Brian 2013-02-08 23:12:17

只要把不同id像阵列上:

var stateStore = new Memory({ 
     data: [ 
      {name:"Alabama", id:"AL"}, 
      {name:"Alaska", id:"AK"} 
       ] 
}); 
  1. 如果你的阵列没有idonChange事件将不触发
  2. 如果两个id相同,onChange事件的价值将第一次开火。

@布赖恩 如果你把对象的ID,如:

var stateStore = new Memory({ 
     data: [ 
      {name:"Alabama", id:{val:"dummy1"}, 
      {name:"Alaska", id:{val:"dummy2"} 
       ] 
}); 

即使两个ID对象是彼此不同的,该事件将不会开火,第二次是因为FilteringSelect不会检查两个ID为:

{val:"dummy1"}=={val:"dummy2"} 

,但它会检查作为

"[object Object]"=="[object Object]" //both are same and no onChange event will be fired