如果之前使用过查找,Ext.form.Panel 无法正确计算消耗记录上的脏数据

问题描述 投票:0回答:1

我正在尝试绑定到表单的脏属性 但是,看起来处理不正确

请检查小提琴的代码示例和错误描述

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()

我正在寻找问题的正确解决方案

谢谢!

extjs extjs7 formpanel
1个回答
0
投票

首先,在您当前的代码中,

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);
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.