Issue #2660Opened March 16, 2020by just-vicu1 reactions

[QUESTION] Reinit model's components function

Question

Hello guys,

I have a custom component with different structure based on prop's value. How can i recall/reinit model's components function on prop change event.

    const EDC = editor.DomComponents;

    const TableType  = EDC.getType('table'),
          TableModel = TableType.model,
          TableView  = TableType.view;

    EDC.addType('product', {
        isComponent: (el) => 'product' in el.dataset,
        model      : TableModel.extend({
            defaults: {
                ...TableModel.prototype.defaults,
                attributes : {
                    width         : '100%',
                    border        : 0,
                    cellspacing   : 0,
                    cellpadding   : 0,
                    'data-product': '',
                },
                arrangement: 'v',
                traits     : [
                    {
                        type      : 'select',
                        name      : 'arrangement',
                        label     : 'Arrangement',
                        changeProp: 1,
                        options   : [
                            {
                                value: 'h',
                                label: 'Horizontal',
                            },
                            {
                                value: 'hi',
                                label: 'Horizontal inverse',
                            },
                            {
                                value: 'v',
                                label: 'Vertical',
                            },
                        ],
                    },
                ],
                components : model =>
                {
                    const arrangement = model.get('arrangement') || 'v';

                    let pBody;

                    if (arrangement === 'v')
                    {
                        pBody = [
                            _wrapComp('row', pImg, commonProps),
                            _wrapComp('row', pInfo, commonProps),
                        ];
                    }
                    else
                    {
                        pImg.style['width'] = '200px';

                        const comps = arrangement === 'h'
                            ? [pImg, pInfo]
                            : [pInfo, pImg];

                        pBody = [
                            _wrapComp('row', comps, commonProps),
                        ];
                    }

                    return {
                        type      : 'tbody',
                        components: pBody,
                        ...commonProps,
                    };
                },
            },
        }),
        view       : TableView.extend({
            onRender()
            {
                const pItem = this.model.get('product') || {};
                const pInfo = {
                    img  : pItem.image || require('~/assets/img/product-ph/select-t.png'),
                    name : pItem.name || 'Product name',
                    price: pItem.price || '00.00',
                    url  : pItem.url || url.front,
                };

                this.model.onAll((m) =>
                {
                    const v  = m.getView();
                    const vm = v.model;

                    switch (vm.get('uid'))
                    {
                        case 'url':
                            v.setAttribute('href', pInfo.url);
                            break;

                        case 'img':
                            v.setAttribute('src', pInfo.img);
                            break;

                        case 'name':
                            vm.set('content', pInfo.name);
                            break;

                        case 'price':
                            vm.set('content', pInfo.price);
                            break;
                    }
                });
            },
        }),
    });

Thank you in advance.

Answers (2)

artfMarch 19, 20201 reactions

I think this.components(this) will throw the Maximum call stack size exceeded error as you're trying to append the component to itself. Probably you have to try this

this.components(
	this.__proto__.defaults.components(this)
)

I'd probably suggest, in this case, to isolate the function to make things more cleaner

const createComponents = (model) => ...

EDC.addType('product', {
....
	defaults: {
		...
		components: createComponents,
	}
	...
		this.listenTo(this, 'change:propName', () => 
			this.components(createComponents(this))
		)
pouyamiralayiMarch 16, 20200 reactions

Hi @V1cu you can register your listeners inside the init hook like below:

model: {
            init() {
                this.listenTo(this, 'change:propName', () => this.components(this))
            },
}

Cheers!

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.