Javascript ExtJS 5.1.1立即在ViewModel中激活绑定
似乎我对绑定时间有一些误解。我有一个简单的组合框,其值绑定到viewmodel中的某个对象。选择新值,触发更改事件,该事件在setValue方法之后触发,因此我的新值已设置,但我的viewmodel尚未更新。何时更新我的viewmodel?我找到了一些关于scheduler的信息,上面说我需要运行notify()方法来立即将更改应用到viewmodel,但这对我毫无帮助Javascript ExtJS 5.1.1立即在ViewModel中激活绑定,javascript,extjs,mvvm,data-binding,extjs5,Javascript,Extjs,Mvvm,Data Binding,Extjs5,似乎我对绑定时间有一些误解。我有一个简单的组合框,其值绑定到viewmodel中的某个对象。选择新值,触发更改事件,该事件在setValue方法之后触发,因此我的新值已设置,但我的viewmodel尚未更新。何时更新我的viewmodel?我找到了一些关于scheduler的信息,上面说我需要运行notify()方法来立即将更改应用到viewmodel,但这对我毫无帮助 Ext.define('MyModel', { extend: 'Ext.data.Model', idPro
Ext.define('MyModel', {
extend: 'Ext.data.Model',
idProperty: 'foo',
fields: [{
name: 'bar',
type: 'string'
}]
});
Ext.define('MyViewModel',{
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.my',
data: {
testObj: {
foo: null,
bar: null
}
},
stores:{
combostore: {
model: 'MyModel',
data: [{
foo: '1',
bar: 'qwerty'
},{
foo: '2',
bar: 'ytrewq'
}]
}
}
});
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.my',
onChange: function() {
var vm = this.getViewModel();
vm.notify();
console.log(vm.get('testObj.foo'));//supposed to be current value
}
});
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('Ext.container.Viewport', {
controller: 'my',
viewModel: {
type: 'my'
},
layout : 'vbox',
items : [
{
xtype : 'combo',
valueField: 'foo',
displayField: 'bar',
queryMode: 'local',
bind: {
store: '{combostore}',
value: '{testObj.foo}'
},
listeners:{
change: 'onChange'
}
}
]
});
}
});
还有小提琴:您不应该直接在viewmodel上调用notify。这是私人的: 只需通过调用vm.setData({})来设置数据 你可以考虑下面的例子,在这里我使用一个公式来获得组合框的选择模型。请注意,我删除了侦听器,添加了对组合框的引用,并创建了一个公式来绑定到所选记录的深度
Ext.define('MyModel', {
extend: 'Ext.data.Model',
idProperty: 'foo',
fields: [{
name: 'bar',
type: 'string'
}]
});
Ext.define('MyViewModel',{
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.my',
data: {
testObj: {
foo: null,
bar: null
}
},
stores:{
combostore: {
model: 'MyModel',
data: [{
foo: '1',
bar: 'qwerty'
},{
foo: '2',
bar: 'ytrewq'
}]
}
},
formulas: {
currentRecord: {
bind: {
bindTo: '{myCombo.selection}',
deep: true
},
get: function(record) {
return record;
},
set: function(record) {
this.set('currentRecord', record);
}
}
}
});
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.my',
onChange: function(cb, newValue, oldValue) {
var vm = this.getViewModel();
console.log('newValue', newValue);
console.log('oldValue', oldValue);
this.getViewModel().setData({'testObj': {'foo': newValue}});
console.log(vm.get('testObj.foo'));//supposed to be current value
}
});
Ext.application({
name : 'Fiddle',
launch : function() {
var vp = Ext.create('Ext.container.Viewport', {
controller: 'my',
viewModel: {
type: 'my'
},
layout : 'vbox',
items : [
{
xtype : 'combo',
reference: 'myCombo',
valueField: 'foo',
displayField: 'bar',
queryMode: 'local',
bind: {
store: '{combostore}',
value: '{testObj.foo}'
}/*,
listeners:{
change: 'onChange'
}*/
},
{
xtype: 'label',
bind: {
text: '{currentRecord.foo}'
}
}
]
});
/* Just an example. You could also select records on the combo itself */
vp.getViewModel().setData({'testObj': {'foo': '2'}});
}
});
延迟将是你的救星:
onChange: function() {
var vm = this.getViewModel();
Ext.defer(function(){
console.log(vm.get('testObj.foo'));//supposed to be current value
},10,this);
}
请使用
选择
事件,而不是更改
我认为更改事件甚至在设置值之前触发。我知道这是一个延迟响应,但我认为这个问题仍然相关。看到这把小提琴了吗 从本质上讲,这个想法是,您监听绑定变量的更改,而不是监听组合框选择的更改(这会触发绑定变量的重新计算) 关键代码在我为视图模型添加的构造函数中:
Ext.define('MyViewModel',{
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.my',
// added this to enable the binding
constructor: function () {
var me = this;
me.callParent(arguments);
me.bind('{selectedItem}', function (value) {
console.log('combobox selected item changed (bar value): ' + (value === null ? "null": value.get('bar')));
console.log(me.getView().getController());
});
me.bind('{testObj.foo}', function (value) {
console.log('combobox value (foo value): ' + value);
// you can access the controller
console.log(me.getView().getController());
});
},
data: {
testObj: {
foo: null,
bar: null
},
selectedItem: null,
},
stores:{
combostore: {
model: 'MyModel',
data: [{
foo: '1',
bar: 'qwerty'
},{
foo: '2',
bar: 'ytrewq'
}]
}
}
});
下面是视图(注意绑定到选择):
绑定选择是没有必要的,但我还是将其作为另一个选项包括在内,因为有时您可能希望在绑定到列表的存储中存储其他数据
我希望这能帮助其他人。我相信
vm.notify()
不会同步完成它的工作。请注意,将delay:1
选项添加到侦听器配置中会起到作用,即使vm.notify()
也会变得多余。如果必须使用delay:1
它应该会提醒所有人你做错了什么。以这种方式调用notify()
也是如此..1。默认情况下,存储的autoSync
config设置为false。对于viewModel中的comboStore,您可能必须将其设置为true2.您不应该在组合的onChange事件中测试存储,因为组合没有时间同步您的存储…|备注:在extjs中,您不会更改组合值,但会更改存储内容,因此,如果您想检查组合中的任何更改,请在其存储中进行测试。谢谢回复,但我不想手动使用setData()
或创建公式来修复此简单绑定。我只想知道,调用setValue()
后,我的viewmodel何时准备就绪,以及为什么要将delay:1
或buffer:1
添加到侦听器配置中,这将实现访问combobox change事件中的值的技巧,如@DrakeES所述。我想我应该在viewmodel中查看Ext.util.Scheduler
,因为我发现了一些有趣的配置,比如tickDelay:5
,默认设置为5毫秒。然后,在为将执行下一个notify.TickDelay的计时器创建延迟函数时使用的配置确实用于此。不幸的是,我没有发现将TickDelay设置为更高的值非常有用,因为它设置为整个viewmodel。而且我相信它是私人的,所以你不能依赖它的存在。。
Ext.define('MyViewModel',{
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.my',
// added this to enable the binding
constructor: function () {
var me = this;
me.callParent(arguments);
me.bind('{selectedItem}', function (value) {
console.log('combobox selected item changed (bar value): ' + (value === null ? "null": value.get('bar')));
console.log(me.getView().getController());
});
me.bind('{testObj.foo}', function (value) {
console.log('combobox value (foo value): ' + value);
// you can access the controller
console.log(me.getView().getController());
});
},
data: {
testObj: {
foo: null,
bar: null
},
selectedItem: null,
},
stores:{
combostore: {
model: 'MyModel',
data: [{
foo: '1',
bar: 'qwerty'
},{
foo: '2',
bar: 'ytrewq'
}]
}
}
});
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('Ext.container.Viewport', {
controller: 'my',
viewModel: {
type: 'my'
},
layout : 'vbox',
items : [
{
xtype : 'combo',
valueField: 'foo',
displayField: 'bar',
queryMode: 'local',
bind: {
store: '{combostore}',
value: '{testObj.foo}',
selection: '{selectedItem}'
},
listeners:{
change: 'onChange'
}
}
]
});
}
});