TableView'click'侦听器被忽略

时间:2013-11-20 09:30:18

标签: titanium appcelerator titanium-mobile titanium-alloy backbone-collections

我在我的控制器中动态构建一个TableView,工作正常:初始表按预期显示初始集合数据。

问题是当我点击表格行时,会忽略TableView的“click”事件侦听器。我在浏览器中测试,我甚至从未看到控制台事件文件(请参阅控制器文件中的注释)。以下所有相关代码段:

在我的alloy.js我设置了一个骨干集合:

function defaultTodo(name) { return {name: name, done: false}; }
function doneTodo(name) { return {name: name, done: true}; }
Alloy.Collections.todos = new Backbone.Collection();
Alloy.Collections.todos.reset([
        defaultTodo('Apples'), // create not yet done todo
        defaultTodo('Banana'),
        defaultTodo('Paper Towels'),
        defaultTodo('Broccoli'),
        doneTodo('Beans'),    // create already done todo
        doneTodo('Water'),
        doneTodo('Blueberries'),
        doneTodo('Stir Fry')
])

这是我的index.js控制器:

var todos = Alloy.Collections.todos;

function redrawTable() {

    // clear all the old data
    // See http://developer.appcelerator.com/question/49241/delete-all-rows-in-a-tableview-with-a-single-click
    $.table.setData([]);

    // Create and add the TableViewSections
    var alreadyDone = Ti.UI.createTableViewSection({ headerTitle: "Already Done" });
    var needsDoing = Ti.UI.createTableViewSection({ headerTitle: "Needs Doing" });
    $.table.appendSection(needsDoing);
    $.table.appendSection(alreadyDone);

    // Add the todo to the appropriate sections
    todos.forEach(function(todo) {
        var section = todo.get('done') ? alreadyDone : needsDoing;
        addEntry(todo, section);
    });

    // Add the click listener
    // THIS LISTENER IS IGNORED ********************************
    $.table.addEventListener('click', function(e) {
        console.log(e);
        todos.at(e.index).set('done', true);
        todos.trigger('change');
    }); 

    // Helper function to add a row to a section
    function addEntry(todo, section) {
        var row = Ti.UI.createTableViewRow({
            title: todo.get('name'),
            className: "row"
        });
        section.add(row);
    }
}

// Redraw our table each time our todos collection changes
todos.on('change', redrawTable);

// Trigger a change event to draw the initial table
todos.trigger('change');

$.index.open();

这是index.xml查看文件:

<Alloy>
    <Window class="container">
        <Label id="test" class="header">My Grocery List</Label>
        <TextField id="newItem"/>
        <TableView id="table">
        </TableView>
    </Window>
</Alloy>

更新:工作代码

除了以下更改之外,我还在xml中添加了onClick="markDone"

function markDone(e) {
    console.log(e.row.todo);
    e.row.todo.set('done', true);
    todos.trigger('change');
} 

function redrawTable() {

    // clear all the old data
    // See http://developer.appcelerator.com/question/49241/delete-all-rows-in-a-tableview-with-a-single-click
    $.table.setData([]);
    var rows = []; 
    var done = [];
    var doing = [];

    // Add the todo to the appropriate sections
    todos.forEach(function(todo) {
        var row = Ti.UI.createTableViewRow({
            title: todo.get('name'),
            className: "row"
        });
        row.todo = todo; 

        todo.get('done') ? done.push(row) : doing.push(row);

    });

    // Create and add the TableViewSections
    rows.push(Ti.UI.createTableViewSection({ headerTitle: "Needs Doing" }));
    rows = rows.concat(doing);  
    rows.push(Ti.UI.createTableViewSection({ headerTitle: "Already Done" }));
    rows = rows.concat(done);

    $.table.setData(rows);

};

1 个答案:

答案 0 :(得分:0)

我使用您提供的文件创建了全新项目,并且eventListener工作正常。但是还有其他一些错误:

  1. 在redrawTable()函数中创建侦听器,每次单击TableView中的某些内容时都会执行该函数。因此,在开始时您有一个eventListener但在每次单击后都会复制所有侦听器。

  2. 在事件处理程序中使用index属性查找要更新的Backbone模型对象的索引。 index属性指示给定行在TableView中显示的位置。当您在段之间移动行时,它们的索引正在发生变化。在您的情况下,最好检查e.row.name属性并使用Backbone.Collection.findWhere()方法。如果用户可以在列表中有两个具有相同名称的项目,则必须创建其他属性以确定应更改模型中的哪个对象。

  3. 您应该在将部分添加到表之前向部分添加行。在你的情况下,表非常简单,所以你可以创建一个简单的对象数组(带有标题和可选的标题属性),而不是做循环,并将其传递给$.table.setData()

  4. 最好在触发任何自定义事件之前等待主视图上触发的postlayout事件,以确保创建整个视图并启动所有对象。

  5. 检查下面的重写index.js代码,看看它是如何完成的。

    var todos = Alloy.Collections.todos;
    
    function redrawTable() {
        var done = todos.where({done: true}).map(function(elem) {
            return { title: elem.get('name') };
        });
        if (done.length > 0) {
            done[0].header = 'Already Done';
        }
    
        var notdone = todos.where({done: false}).map(function(elem) {
            return { title: elem.get('name') };
        });
        if (notdone.length > 0) {
            notdone[0].header = 'Needs Doing';
        }
    
        $.table.setData( done.concat(notdone) );
    }
    
    $.table.addEventListener('click', function(e) {
        todos.where({ name: e.row.title }).forEach(function(elem){
            elem.set('done', !elem.get('done'));
        });
        todos.trigger('change'); // Redraw table
    });
    
    // Redraw our table each time our todos collection changes
    todos.on('change', redrawTable);
    
    // Trigger a change event to draw the initial table
    $.index.addEventListener('postlayout', function init(){
        todos.trigger('change');
        // Remove eventListener, we don't need it any more.
        $.index.removeEventListener('postlayout', init);
    })
    
    $.index.open();
    

    redrawTable()可能会有更多的重构,但我离开了它,因此更容易阅读。

    要阅读有关操纵TableView的更多信息,请检查此Appcelerator documentation page