ExtJS - 如何使用自己的 isValid 和 hasInvalidField 方法实现容器

ExtJS - How to implement a container with its own isValid and hasInvalidField methods

例如,假设我们有三个 phone 数字字段:mobilehomebusiness,我们希望将其封装为 contact项。

phone 号码字段可以为空,如果没有,则有自己的有效性检查,联系人项目有自己的有效性检查,必须至少提供一个号码。

我正在考虑做这样的事情:

Ext.define('My.widgets.contact', {
    // To make use of Ext.form.Labelable mixin
    extend: 'Ext.form.fieldcontainer',
    xtype: 'contact',
    alias: 'widget.contact',
    requires: [
        'My.widgets.phone'
    ],
    mixins: [
        // To link in isValid and other methods
        'Ext.form.field.Field'
    ],
    items: [
        {
            xtype: 'phone',
            fieldLabel: 'mobile'
        },
        {
            xtype: 'phone',
            fieldLabel: 'home'
        },
        {
            xtype: 'phone',
            fieldLabel: 'business'
        }
    ],
    isValid: function() {
        let valid = false;
        if (this.callParent(arguments)) {
            for (const item in this.getItems()) {
                if (item.getValue() != '') {
                    valid = true;
                    break;
                }
            }
        }
        return valid;
    }
});

这样做正确吗?

我们的想法是让多余的绒毛最少。例如,表单面板具有不需要的可停靠、按钮、页眉和页脚元素。另外,我已经阅读了关于在一个页面上有多个表单项的 ExtJS 中的问题,因此希望避免在单个页面上使用顺序或嵌套表单。

另一种方法可能是使用 Ext.form.LabelableExt.form.field.Field 混合扩展 Ext.container.Container。那行得通吗?

在 ExtJs 中 fieldcontainer have method query 所以你用它来检查你的验证。

Query 检索与传递的选择器匹配的所有后代组件。使用此容器作为其根执行 Ext.ComponentQuery.query。

因为你已经使用了 this.getItems() 它会 return fieldcontainer 的所有项目,无论它包含什么。在这种情况下,您需要维护条件以仅检查字段的 getValue()

Query 将 return 仅您要检查的那个组件。

我创建了一个 Sencha Fiddle 演示,希望这能帮助您实现您的解决方案。

//Custom xtype for phone
Ext.define('Ext.form.field.Phone', {
    extend: 'Ext.form.field.Text',
    alias: 'widget.phone',
    xtype: 'phone',
    maskRe: /[\d\.]/,
    regex: /^\d+(\.\d{1,2})?$/,
    maxLength: 11,
    enforceMaxLength: true
});

//Contact details
Ext.define('ContactForm', {
    extend: 'Ext.form.FieldContainer',
    alias: 'widget.contact',
    xtype: 'contact',
    flex: 1,
    layout: 'vbox',
    defaults: {
        xtype: 'phone'
    },
    items: [{
        fieldLabel: 'mobile'
    }, {
        fieldLabel: 'home'
    }, {
        fieldLabel: 'business'
    }],
    isValid: function () {
        return this.query('phone[value=""]').length > 0;//you can also use like this { this.query('phone[value!=""]') };
    }
});

//Panel this will contain contact
var panel = Ext.create('Ext.panel.Panel', {
    itemId: 'myPanel',
    bodyPadding: 5,
    width: 300,
    renderTo: Ext.getBody(),
    title: 'Contact Details',
    items: [{
        xtype: 'contact'
    }],
    buttons: [{
        text: 'Submit Details',
        handler: function () {
            var contactFrm = this.up('#myPanel').down('contact'), //you also use like this this.up('panel').down('contact')
                title = 'Success',
                msg = 'Good you have entered the contact details..!';
            if (!contactFrm.isValid()) {
                title = 'Error';
                msg = 'Plese enter at least one contact detail..!'
            }
            Ext.Msg.alert(title, msg);
        }
    }]
});