我正在尝试绑定到表单的脏属性 但是,看起来处理不正确
请检查小提琴的代码示例和错误描述
https://fiddle.sencha.com/#fiddle/3ovk
// define model
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'int', convert: null},
{name: 'phone', type: 'string'},
{name: 'alive', type: 'boolean', defaultValue: true, convert: null}
],
});
// create new record, some filed should have empty string (ex. phone)
var user = Ext.create('User', {
id : 'ABCD12345',
name : 'Conan',
age : 123,
phone: ''
// phone: '123456789' // if the field is not empty, then dirty updated correctly
});
// create basic form
// (viewModel and binding just to check form dirty property)
var form = Ext.create({
xtype: 'formpanel',
viewModel: true,
reference: 'formref',
publishes: ["dirty"],
trackResetOnLoad: true,
items: [
{
xtype: 'textfield',
label: 'id',
name: 'id'
},
{
xtype: 'textfield',
label: 'name',
name: 'name'
},
{
xtype: 'textfield',
label: 'age',
name: 'age'
},
{
xtype: 'textfield',
label: 'phone',
name: 'phone',
},
{
xtype: 'textfield',
bubbleDirty: false,
bind: '{formref.dirty}'
},
]
});
Ext.application({
name : 'Fiddle',
launch : function() {
// render container and lookup for something to reproduce form durty bug
var container = Ext.create({
xtype: 'container',
items: [form]
})
Ext.Viewport.add(container);
// comment next line to check formref.dirty is set correctly
var f = container.lookup('formref');
// lookup will call
// beginSyncChildDirty: function() {
// this._childDirtyState = { counter: 0, ready: false };
// },
// so, it initialize counter
// as phone field value is not changed, it will call adjustChildDirtyCount with false
// childDirtyState.counter += dirty ? 1 : -1;
// now, the childDirtyState.counter is equal to -1
// and !!childDirtyState.counter equal to true
// me.setDirty(!!childDirtyState.counter);
// formref.dirty is now set to true
form.setRecord(user);
}
});
重现的关键 - 在将记录设置到表单面板之前调用lookup()
我正在寻找问题的正确解决方案
谢谢!
首先,在您当前的代码中,
lookup
甚至找不到您的表单面板。通过在 console.log(f);
之后添加 var f = container.lookup...
来检查这一点。它将记录 null
。
通过将
referenceHolder: true,
配置添加到 container
可以轻松解决此问题。之后它就会在容器内找到表单面板。
至于你的问题,我猜这是某种竞争条件。
launch
函数在启动 Ext JS 应用程序的早期阶段被调用,框架可能还没有完全准备好设置组件。通常 lookup
是从控制器或其他已经完成初始化的地方调用的。
尝试向表单面板添加一个按钮并从那里调用
lookup
,并从 lookup
函数中删除 launch
调用。
buttons: [{
text: 'Lookup test',
handler: function (button) {
var f = button.up('formpanel').up('container').lookup('formref');
console.log(f);
}
}],
此后,即使您按下按钮,脏绑定也会按预期工作。
包含建议更改的完整代码:
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [{
name: 'name',
type: 'string'
}, {
name: 'age',
type: 'int',
convert: null
}, {
name: 'phone',
type: 'string'
}, {
name: 'alive',
type: 'boolean',
defaultValue: true,
convert: null
}],
});
var user = Ext.create('User', {
id: 'ABCD12345',
name: 'Conan',
age: 123,
phone: ''
});
var form = Ext.create({
xtype: 'formpanel',
viewModel: true,
reference: 'formref',
publishes: ["dirty"],
trackResetOnLoad: true,
items: [{
xtype: 'textfield',
label: 'id',
name: 'id'
}, {
xtype: 'textfield',
label: 'name',
name: 'name'
}, {
xtype: 'textfield',
label: 'age',
name: 'age'
}, {
xtype: 'textfield',
label: 'phone',
name: 'phone',
}, {
xtype: 'textfield',
bubbleDirty: false,
bind: '{formref.dirty}'
}],
buttons: [{
text: 'Lookup',
handler: function (button) {
var f = button.up('formpanel').up('container').lookup('formref');
console.log(f);
}
}]
});
Ext.application({
name: 'Fiddle',
launch: function () {
var container = Ext.create({
referenceHolder: true,
xtype: 'container',
items: [form]
})
Ext.Viewport.add(container);
form.setRecord(user);
}
});