1

我正在使用 arcgis Javascript Api 3.7(其中包括 dojo 1.9.1),并且我一直在开发一个自定义模板化 dijit,它有两个 filterSelect 控件,第一个被正确填充,我有第二个被填充时用户从第一个项目中选择一个项目,在该特定时刻设置其数据存储。第二个filteringSelect每次都会正确填充,但是onchange事件会发生一些事情,因为函数处理程序永远不会被触发,我需要对第二个FilterinSelect的onchange事件做一些其他的工作。

似乎有些东西被第二个过滤选择弄乱了(用处理程序上下文猜测一些东西),但我还想不通。

我的两个过滤控件模板声明(我的 dijit html 模板的一部分:

                <tr>
                <td>
                    Capa:
                </td>
                <td>
                    <input data-dojo-type="dijit.form.ComboBox" name="layerDijit" id="layerDijit"
                           data-dojo-props="autoComplete:true, required:true, searchAttr:'name', style:'width:100%;'"
                           data-dojo-attach-point="layerDijit" data-dojo-attach-event="change:_handleLayerSelected"/>
                </td>
            </tr>
            <tr>
                <td>
                    Campo:
                </td>
                <td>
                    <input data-dojo-type="dijit.form.FilteringSelect" name="fieldDijit" id="fieldDijit"
                           data-dojo-props="autoComplete:true, required:true, searchAttr:'name', style:'width:100%;'"
                           data-dojo-attach-point="fieldDijit" data-dojo-attach-event="change:_handleFieldSelected"/>
                </td>
            </tr>

Dijit JS 脚本:

填充第一个过滤选择的代码

postCreate: function() {
        this.inherited(arguments);

        ....

        this.rootMapLayer = this.map.getLayer("ELAPAS");
        if (this.rootMapLayer.loaded){
            this.listLayers(this.rootMapLayer);
        }
        else{
            this.rootMapLayer.on("load", lang.hitch(this, this.listLayers));
        }

        //enlace de eventos (tested this, and it doesn't work for the second filtering select either)
        //this.fieldDijit.on('change', lang.hitch(this, this._handleFieldSelected));
        //this.layerDijit.on('change', lang.hitch(this, this._handleLayerSelected));
    },

listLayers: function() {

        var layerInfos = [];

        layerInfos = array.filter(this.rootMapLayer.layerInfos,function(info,index){
            return info.subLayerIds === null;
        });

        if(layerInfos.length === 0) {
            console.error("No se encontro ninguna capa para el servicio de mapa seleccionado");
            return;
        }

        var layersStore = new Memory({
            data: layerInfos
        });

        this.layerDijit.set('store', layersStore);
    },

处理第一个过滤选择中的选择更改的代码称为 layerDijit 并为第二个过滤选择(FieldDijit)加载数据:

_handleLayerSelected: function () {
        var selectedLayer = this.layerDijit.item;

        if(this.getSelectedLayerUrl() === null) {
            return;
        }

        //Se limpia el campo actual
        this.fieldDijit.set("value", "");

        //Se arma la url del layer específico para traer la información de la capa (sus campos)
        var layerUrl = this.rootMapLayer.url + "/" + selectedLayer.id;

        esri.request({
            url: layerUrl,
            content: {
                f: "json"
            },
            handleAs: "json",
            callbackParamName: 'callback',
            load: lang.hitch(this, '_handleLayerInfo'),
            error: lang.hitch(this, '_handleLayerInfoError')
        });
    },
_handleLayerInfo: function(data) {
        var layerInfo = data;
        if (!layerInfo.fields) {
            console.error("No se pudo obtener la información de los campos de la capa");
            return;
        }

        var fieldsStore = new Memory({
            data: layerInfo.fields
        });

        this.fieldDijit.set('store', fieldsStore);
    },

    getSelectedLayerUrl: function(){
        var selectedLayer = this.layerDijit.item;
        if(!selectedLayer) {
            return null;
        }
        //Se arma la url del layer específico para traer la información de la capa (sus campos)
        return this.rootMapLayer.url + "/" + selectedLayer.id;
    },

    _handleLayerInfoError: function(err){
        console.error(err);
    },

没有被触发的函数,应该处理第二个过滤选择的 se change 事件的函数:

_handleFieldSelected: function () {
        alert("doesn't get fired");
        /*var selectedField = this.fieldDijit.item;

        if(!selectedField) {
            return;
        } */
    },

你能给我一些关于这个问题的建议吗?,我做错了什么?

提前致谢

4

2 回答 2

3

主教,感谢您的回答,我想我的问题并不清楚,我明白当用户(或后台的某些东西)更改 FilteringSelect 中的选定项目时,应该触发“onChange”事件,所以我的问题是,当用户从第二个 FilteringSelect 控件中选择一个项目时,它的 onchange 事件没有被触发。

正如您建议的那样,我尝试了一个更简单的示例(使用硬编码的内存对象)并且它确实有效,所以我开始深入挖掘并意识到问题出在我的内存对象上,

显然,当您声明一个 Memory 对象时,您必须确保在数组集合对象中存在一个 ID,如下例所示:

var stateStore = new Memory({
            data: [
                {name:"Alabama" id:"AL"},
                {name:"Alaska", id:"AK"},
                {name:"American Samoa", id:"AS"},
                {name:"Arizona", id:"AZ"},
                {name:"Arkansas", id:"AR"},
                {name:"Armed Forces Europe", id:"AE"},
                {name:"Armed Forces Pacific", id:"AP"},
                {name:"Armed Forces the Americas", id:"AA"},
                {name:"California", id:"CA"},
                {name:"Colorado", id:"CO"},
                {name:"Connecticut", id:"CT"},
                {name:"Delaware", id:"DE"}
            ]
        });
        this.fieldDijit.set('store', stateStore);

当你没有在内存对象声明中明确告诉它时,就推测有一个字段叫做“id”。就我而言,我在第二个过滤选择中分配给内存对象的数组没有名为“id”的字段

所以我改变了:

var fieldsStore = new Memory({
            data: layerInfo.fields
        });

为了:

var fieldsStore = new Memory({
            idProperty: "name", //added this
            data: layerInfo.fields
        });

现在,当第二个过滤器选择中的选定项目发生变化时,该事件将被触发。

于 2013-10-26T20:29:40.063 回答
1

根据我正在阅读的内容,我认为您期待此代码:

this.fieldDijit.set('store', fieldsStore);

导致您的共同依赖选择安排中的第二个选择触发其更改事件 - 毕竟,选择已经“更改”,因为它具有不同的存储。

但这不是 change 事件的含义。更改事件意味着用户更改了所选值。因此,在设置新商店后,如果您在第二个下拉菜单中选择一个值,您的更改处理程序应该会触发。

这是一个我认为将您的示例简化为最简单元素的示例。请注意,当您选择第一个框的值时,第二个框的存储更改但其 onchange 事件不会触发(如预期的那样)。但是当您选择第二个框的值时,它的 onchange 确实会触发(如预期的那样):

<!DOCTYPE html>
<html>
    <head>
        <link href='//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dijit/themes/claro/claro.css' rel='stylesheet' type='text/css' />
        <script src='//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js'></script>
    </head>
    <body class='claro'>
        <div data-dojo-id='s1' data-dojo-type='dojo/store/Memory' data-dojo-props='data:[{id:1,name:"A"}]'></div>
        <div data-dojo-id='s2' data-dojo-type='dojo/store/Memory' data-dojo-props='data:[{id:1,name:"C"}]'></div>
        <select data-dojo-id='first' data-dojo-type='dijit/form/ComboBox' data-dojo-props='store:s1'>
            <script type='dojo/method' event='onChange'>
                second.set('store', s2);
            </script>
        </select>

        <select data-dojo-id='second' data-dojo-type='dijit/form/ComboBox'>
            <script type='dojo/method' event='onChange'>
                alert('I am changed');
            </script>
        </select>

        <script type='text/javascript'>
        require(['dojo/ready', 'dojo/parser'], function (ready, Parser) {
            ready(function () {
                Parser.parse().then(function () {
                });
            });
        });
        </script>
    </body>
</html>

如果我不理解您描述的错误,您可以发送一个更简单的测试用例吗?

于 2013-10-25T19:14:15.247 回答