проблема с областью действия dojo.connect / dojo.hitch?

У меня есть класс программиста, который заполняет ul именами проектов и флажками - при нажатии флажка должно отображаться всплывающее диалоговое окно с идентификатором программиста и именем проекта. Предполагается, что dojo.connect устанавливает onclick для каждого li, но проект (i) по умолчанию использует последнее значение (windows). Есть идеи, почему это происходит?

...
projects: {"redial", "cms", "android", "windows"},
name: "Chris",
id: "2",

constructor: function(programmer) {
    this.name = programmer.name;
    this.id = programmer.id;
    this.projects = programmer.projects;
},

update: function(theid, project) {
    alert(theid + ", " + project);
},

postCreate: function() {
    this.render();

    // add in the name of the programmer
    this.programmerName.innerHTML = this.name;

    for(var i in this.projects) {
        node = document.createElement("li");
        this.programmerProjects.appendChild(node);
        innerNode = document.createElement("label");
        innerNode.setAttribute("for", this.id + "_" + i);
        innerNode.innerHTML = i;
        node.appendChild(innerNode);
        tickNode = document.createElement("input");
        tickNode.setAttribute("type", "checkbox");
        tickNode.setAttribute("id", this.id + "_" + i);
        if(this.projects[i] == 1) {
            tickNode.setAttribute("checked", "checked");
        }

        dojo.connect(tickNode, 'onclick', dojo.hitch(this, function() {  
            this.update(this.id, i)
        }));
        node.appendChild(tickNode);
    }   
},  

person Community    schedule 27.08.2009    source источник


Ответы (3)


Только что узнал, что на сцепку можно навесить дополнительные параметры:

dojo.connect(tickNode, 'onclick', dojo.hitch(this, function() {  
            this.update(this.id, i)
}));

должно быть:

dojo.connect(tickNode, 'onclick', dojo.hitch(this, "update", this.id, i));
person Community    schedule 27.08.2009

Почему вы вызываете this.render()? Это ваша функция или база виджетов (то есть уже в жизненном цикле)? На всякий случай обязательно вызовите this.inherited(arguments); в постСоздать.

Я предполагаю, что tickNode еще не находится в DOM, чтобы соединение работало. Попробуйте добавить флажок перед настройкой соединения. Последнюю увольняют, потому что она удерживается по ссылке. Вместо этого вы можете попробовать что-то вроде этого:

for(var i = 0; i < this.projects.length; i++) {
    var p = this.projects[i];
    node = document.createElement("li");
    this.programmerProjects.appendChild(node);
    innerNode = document.createElement("label");
    innerNode.setAttribute("for", this.id + "_" + p);
    innerNode.innerHTML = p;
    node.appendChild(innerNode);
    tickNode = document.createElement("input");
    tickNode.setAttribute("type", "checkbox");
    tickNode.setAttribute("id", this.id + "_" + p);
    if(i == 0) { //first item checked?
        tickNode.setAttribute("checked", "checked");
    }

    node.appendChild(tickNode);

    dojo.connect(tickNode, 'onclick', function(e) {
        dojo.stopEvent(e);
        this.update(this.id, p);
    });
}

Я бы также подумал о том, чтобы изучить dojo.create вместо createElement. Удачи!

person Kyle LeNeau    schedule 31.08.2009

В качестве альтернативы, и я думаю, что это чище, вы можете передать контекст в dojo.connect в качестве третьего параметра:

dojo.connect(tickNode, 'onclick', this, function() {  
  this.update(this.id, i);
});
person Justin Johnson    schedule 05.09.2009
comment
Это неаккуратно и создает ненужное закрытие, которое нельзя использовать повторно. - person rxgx; 26.04.2011
comment
И использование dojo.hitch в этой ситуации является ненужным накладным расходом, который стоит больше, чем создание замыкания. - person Justin Johnson; 28.04.2011