我正在使用Ember.js开发一个表编辑器。我创建了一个名为FocusedTextField
的视图,在渲染文本字段时对其进行聚焦。我想实现一个Tab键功能,以便命中选项卡将下一个单元格集中在一行。当前代码将当前选定的单元格更改为不可编辑,并将下一个单元格更改为文本字段,但不会关注下一个字段的值。似乎代码不起作用是时间的影响。什么是解决这个问题的更好方法?
这是我的JSBin:http://emberjs.jsbin.com/tey/12/edit
jQuery 1.10.2 把手1.2.1 Ember 1.1.2
HTML:
<script type="text/x-handlebars" data-template-name="row">
<tr>
{{#collection cellCollection}}
{{view view.content.view}}
{{/collection}}
</tr>
</script>
<script type="text/x-handlebars" data-template-name="cell">
<td {{action "click"}}>
{{#if editMode}}
{{view textField valueBinding=value}}
{{else}}
{{value}}
{{/if}}
</td>
</script>
<script type="text/x-handlebars" data-template-name="table">
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Points</th>
</tr>
{{#collection rowCollection}}
{{view view.content.view}}
{{/collection}}
</table>
</script>
<div id="main"></div>
JavaScript的:
App = Ember.Application.create();
var TemplatedViewController = Ember.Object.extend({
templateFunction: null,
viewArgs: null,
viewBaseClass: Ember.View,
view: function () {
var controller = this;
var viewArgs = this.get('viewArgs') || {};
var args = {
template: controller.get('templateFunction'),
controller: controller
};
args = $.extend(viewArgs, args);
return this.get('viewBaseClass').extend(args);
}.property('templateFunction', 'viewArgs'),
appendView: function (selector) {
this.get('view').create().appendTo(selector);
},
appendViewToBody: function () {
this.get('view').create().append();
},
appendPropertyViewToBody: function (property) {
this.get(property).create().append();
}
});
var FocusedTextField = Ember.TextField.extend({
focusTheTextField: function() {
this.$().focus();
}.on('didInsertElement')
});
var Cell = TemplatedViewController.extend({
row: null,
editMode: false,
value: null,
textField: function () {
var cell = this;
return FocusedTextField.extend({
keyDown: function (event) {
// Hitting the enter key disables edit mode
if (event.keyCode === 13) {
cell.set('editMode', false);
// Hitting the tab key selects the next cell
} else if (event.keyCode === 9) {
cell.set('editMode', false);
var nextCell = cell.getNextCell();
nextCell.set('editMode', true);
}
}
});
}.property(),
flipEditMode: function () {
if (this.get('editMode')) {
this.set('editMode', false);
} else {
this.set('editMode', true);
}
},
click: function () {
console.log('cell clicked, value: '+this.get('value'));
this.flipEditMode();
},
getNextCell: function () {
return this.get('row').getNextCell(this);
},
view: function () {
var controller = this;
return this.get('viewBaseClass').extend({
controller: controller,
templateName: 'cell'
});
}.property()
});
var Row = TemplatedViewController.extend({
headers: ['firstName', 'lastName', 'points'],
firstName: null,
lastName: null,
points: null,
cells: null,
cellCollection: function () {
return Ember.CollectionView.extend({
content: this.get('cells')
});
}.property('cells'),
init: function () {
this._super();
var row = this;
var cells = [];
this.get('headers').forEach(function (item, index, enumerable) {
var header = item;
var value = row.get(header);
var cell = Cell.create({
row: row,
value: value
});
cells.pushObject(cell);
});
this.set('cells', cells);
},
getNextCell: function (cell) {
if (this.get('cells').contains(cell)) {
var lastIndex = this.get('cells').length - 1;
var cellIndex = this.get('cells').indexOf(cell);
if (cellIndex < lastIndex) {
var nextIndex = cellIndex + 1;
return this.get('cells')[nextIndex];
}
}
},
view: function () {
var controller = this;
return this.get('viewBaseClass').extend({
controller: controller,
templateName: 'row'
});
}.property()
});
var rows = [];
var DATA = [
{first_name: 'Jill', last_name: 'Smith', points: 50},
{first_name: 'Eve', last_name: 'Jackson', points: 94},
{first_name: 'John', last_name: 'Doe', points: 80},
{first_name: 'Adam', last_name: 'Johnson', points: 67}
];
DATA.forEach(function (item, index, enumerable) {
var row = Row.create({
firstName: item.first_name,
lastName: item.last_name,
points: item.points
});
rows.pushObject(row);
});
var Table = TemplatedViewController.extend({
view: function () {
var controller = this;
return this.get('viewBaseClass').extend({
controller: controller,
templateName: 'table'
});
}.property(),
rows: null,
rowCollection: function () {
return Ember.CollectionView.extend({
content: this.get('rows')
});
}.property('rows')
});
var table = Table.create({rows: rows});
$(function () {
table.appendView('#main');
});
答案 0 :(得分:3)
将focus()
中的Ember.run.next
电话转接到var FocusedTextField = Ember.TextField.extend({
focusTheTextField: function() {
var self = this;
Ember.run.next( function() { self.$().focus(); });
}.on('didInsertElement')
});
,如下所示:
Ember.run.next
有关{{1}}的说明,请参阅:http://emberjs.com/api/classes/Ember.run.html#method_next Ember运行循环的良好描述:What is Ember RunLoop and how does it work?