You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ext.form.Panel调用lookup后绑定record时dirty属性计算错误

Ext.form.Panel dirty属性计算异常问题修复

问题现象

绑定Ext.form.Panel的dirty属性时发现计算异常:当在给表单面板设置record之前调用lookup()方法,且字段初始值为空字符串时,表单的dirty属性会被错误标记为true。

问题代码示例

// 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('formref')会触发表单的beginSyncChildDirty方法,初始化_childDirtyState.counter为0。当给表单设置record后,空字符串的字段(如phone)会调用adjustChildDirtyCount(false),导致counter被减1变为-1。由于!!-1结果为true,最终表单的dirty属性被错误设置为true。

修复方案

方案1:调整调用顺序(最简单)

将lookup()调用放在setRecord()之后,确保表单先加载record数据,再初始化脏状态计数:

Ext.application({
    name : 'Fiddle',
    launch : function() {
        var container = Ext.create({
            xtype: 'container',
            items: [form]
        })
        Ext.Viewport.add(container);

        // 先设置record,再调用lookup
        form.setRecord(user);
        var f = container.lookup('formref');
    }
});

方案2:重写adjustChildDirtyCount方法(避免计数器负数)

自定义FormPanel,重写adjustChildDirtyCount方法,确保计数器不会小于0:

Ext.define('FixDirtyFormPanel', {
    extend: 'Ext.form.Panel',
    adjustChildDirtyCount: function(dirty) {
        var state = this._childDirtyState;
        if (state) {
            state.counter += dirty ? 1 : -1;
            // 确保计数器不会小于0
            state.counter = Math.max(state.counter, 0);
            this.setDirty(!!state.counter);
        }
    }
});

// 创建表单时使用自定义xtype
var form = Ext.create({
    xtype: 'fixdirtyformpanel',
    viewModel: true,
    reference: 'formref',
    publishes: ["dirty"],
    trackResetOnLoad: true,
    items: [
        // 原字段配置...
    ]
});

方案3:手动重置脏状态(应急处理)

在设置record后手动重置表单和字段的脏状态:

form.setRecord(user);
// 重置表单dirty为false
form.setDirty(false);
// 重置所有字段的原始值,确保后续脏状态判断准确
form.getFields().each(function(field) {
    field.resetOriginalValue();
});

内容的提问来源于stack exchange,提问作者A.Pokidin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:45:28