0

I'd like to create a component which combines other existing components. A simplified example is below:

Ext.define('CCC.ThreeNames', {
    extend: '???',
    alias: 'widget.threenames',
    items: [
        {
            xtype: 'textfield',
            label: 'First',
            itemId: 'first',
            name: 'first'
        },
        {
            xtype: 'textfield',
            label: 'Middle',
            itemId: 'middle',
            name: 'middle'
        },
        {
            xtype: 'textfield',
            label: 'Last',
            itemId: 'last',
            name: 'last'
        }
    ]
});

So let's say I want to use it:

items: [
    {
        xtype: 'threenames',
        itemId: 'applicant',
        name: 'applicant'
    },
    {
        xtype: 'threenames',
        itemId: 'dependent',
        name: 'dependent'
    }
]

First of all, what do I extend ??? from? I was thinking xtype: 'fieldset', but this type isn't considered a form field, so instead when you're pulling data via getValues, it skips the fieldset and iterates down to the text fields. The text fields don't "know" their context, because that's in the parent element, so they just report as first, middle and last, and now there are duplicate fields in the data set.

I was thinking during initialization, maybe the parent component munges the name and prefixes them with its own name, e.g. first, middle, last to applicant.first, applicant.middle, applicant.last, etc. but then that's going to muck up any code in the components that uses the name for whatever.

How to handle this? We'd really like to be able to reuse some complex composite components so that our designers don't have to hand code them all the time, and have the component work as an independent unit to save and retrieve data, so for example form.getValues() pulls out the data, without knowing anything about the composite component.

Would really appreciate a solution to this.

Regarding the possible duplicate suggested by Coderino Javarino: This question is not a duplicate of that one. That component is able to work using a single value for both fields, i.e. the date field interprets the value as a date, the time field interprets the value as a time. In effect it's really just a single component with a custom display type.

  • Possible duplicate of [How to create custom ExtJS form field component?](https://stackoverflow.com/questions/6153362/how-to-create-custom-extjs-form-field-component) – Coderino Javarino Feb 15 '19 at 10:03
  • @CoderinoJavarino - Not a duplicate of that. That component is able to work using a single value for both fields, i.e. the date field interprets the value as a date, the time field interprets the value as a time. In effect it's really just a single component with a custom display type. –  Feb 15 '19 at 13:09
  • What are 'applicant' and 'dependent'? Nested data of loaded record? Could you include models in your example. – Sven Liivak Feb 20 '19 at 14:50
  • @SvenLiivak - instances of `threenames`. No model, WYSIWYG. –  Feb 20 '19 at 20:49

2 Answers2

0

Naming fields requested way is a simple task:

Ext.define('CCC.ThreeNames', {
    extend: 'Ext.container.Container', //you can use Ext.form.Panel for additional functionality
    alias: 'widget.threenames',
    items: [
        { xtype: 'textfield', itemId: 'first', name: 'first', fieldLabel: 'First' },
        { xtype: 'textfield', itemId: 'middle', name: 'middle', fieldLabel: 'middle' },
        { xtype: 'textfield', itemId: 'last', name: 'last', fieldLabel: 'last' },
],
    listeners: {
        beforerender: function() {
            let self = this;
            this.query('textfield').forEach(function(field){
                field.name = self.name + '.' + field.name;
                field.itemId = field.name;
            });
        }
    }
});

using such naming is completely different thing. But as I understood from your comment that MVC pattern is not in use then this solutions should give expected result.

Sven Liivak
  • 1,323
  • 9
  • 10
  • FYI, I did mention that munging `name` is not a desired solution. While the component above doesn't have a model associated with it, I can't guarantee that will always be the case. –  Feb 25 '19 at 17:58
0

Here is the recommended way to achieve what you want

Ext.define('CCC.ThreeNames', {
extend: '???',
**xtype: 'threenames',**
alias: 'widget.threenames',
items: [
    {
        xtype: 'textfield',
        label: 'First',
        itemId: 'first',
        name: 'first'
    },
    {
        xtype: 'textfield',
        label: 'Middle',
        itemId: 'middle',
        name: 'middle'
    },
    {
        xtype: 'textfield',
        label: 'Last',
        itemId: 'last',
        name: 'last'
    }
]});

Now you can use it like this

items: [
    {
        xtype: 'threenames',
        itemId: 'applicant',
        name: 'applicant'
    },
    {
        xtype: 'threenames',
        itemId: 'dependent',
        name: 'dependent'
    }
]
aallord
  • 357
  • 1
  • 12
  • No, it has the same problem. Put that in a form, enter `p, q, r` for one and `a, b, c` for the other, then getting the values returns `{"first":["p","a"],"middle":["q","b"],"last":["r","c"]}`. So there's no differentiator between `applicant` and `dependent` other than the index. Make some changes to the form, and the data ends up being in the wrong place. –  Apr 30 '19 at 14:06
  • Ext.ComponentQuery.query('textfield#applicant') and Ext.ComponentQuery.query('textfield#dependent') would combine the textfields into your desired results of different applicant and dependent results – aallord Apr 30 '19 at 19:04