我在我的控制器中动态构建一个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);
};
答案 0 :(得分:0)
我使用您提供的文件创建了全新项目,并且eventListener工作正常。但是还有其他一些错误:
在redrawTable()函数中创建侦听器,每次单击TableView中的某些内容时都会执行该函数。因此,在开始时您有一个eventListener但在每次单击后都会复制所有侦听器。
在事件处理程序中使用index属性查找要更新的Backbone模型对象的索引。 index属性指示给定行在TableView中显示的位置。当您在段之间移动行时,它们的索引正在发生变化。在您的情况下,最好检查e.row.name属性并使用Backbone.Collection.findWhere()方法。如果用户可以在列表中有两个具有相同名称的项目,则必须创建其他属性以确定应更改模型中的哪个对象。
您应该在将部分添加到表之前向部分添加行。在你的情况下,表非常简单,所以你可以创建一个简单的对象数组(带有标题和可选的标题属性),而不是做循环,并将其传递给$.table.setData()
。
最好在触发任何自定义事件之前等待主视图上触发的postlayout事件,以确保创建整个视图并启动所有对象。
检查下面的重写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。