GrapesJS / grapesjs

Free and Open source Web Builder Framework. Next generation tool for building templates without coding
https://grapesjs.com
BSD 3-Clause "New" or "Revised" License
22.36k stars 4.05k forks source link

QUESTION: How should I receive custom trait modifications in the script? #3329

Closed imouou closed 3 years ago

imouou commented 3 years ago

Hi, @artf, this is a great framework, thank you very much.

I am now using it to create components of the mobile BUI framework, and I ran into a problem, I added a custom trait textarea, how can I make this When the data changes, it is triggered in the output script.

editor.TraitManager.addType('textarea', {
    createInput({
      trait,
      component
    }) {
      // Here we can decide to use properties from the trait
      const el=document.createElement('div');
      el.innerHTML = `
      <textarea class="buiv-textarea" name="${options[0].name}" rows="${options[0].rows}">${options[0].value}</textarea>
    `;
      return el;
    },
    onEvent({
      elInput,
      component,
      event
    }) {
// The data change will reach this callback, you can operate the component, but how can we trigger the parameters received in the script? 
    },
    onUpdate({
      elInput,
      component,
      trait
    }) {
    },
  });

// use trait textarea 
editor.DomComponents.addType("slide", {
    model: defaultModel.extend({
      defaults: {
        ...defaultModel.prototype.defaults,
        name: "slide",
        content: `<div class="bui-slide bui-slide-skin01"></div>`,
        datas: '[{image:""}]',
        traits: [{
          type: 'textarea',
          name: 'datas',
          label: "data",
          changeProp: 1,
        }],
        script() {

          let parentId=this.id;
          // first time it is [{image:""}],  I want to listen 'datas' change trigger here.
          console.log('{[ datas ]}')

        },
      },
    }
    }),
    view: defaultView.extend({
      init() {
        const props=['loop', 'fullscreen', 'height', 'direction', 'visibleNum', 'scrollNum', 'datas', 'autoplay'];

        const reactTo = props.map(prop => `change:${prop}`).join(' ');

        this.listenTo(this.model, reactTo, this.render);

      }
    }),
  });
Ju99ernaut commented 3 years ago

You'll need to add the trait to script-props, you can read more here https://grapesjs.com/docs/modules/Components-js.html#passing-properties-to-scripts

imouou commented 3 years ago

Thanks @Ju99ernaut, If it is some built-in features, when modifying the script can receive the value of the parameter, I am currently experiencing problems: custom feature textarea, can trigger changes such as dom, but the exported script can not receive the value of this parameter, even if the script-props are set: "datas".

Ju99ernaut commented 3 years ago

You can try forcing the script to update:

editor.DomComponents.addType('slide', {
   model: {
      // ...
      init() {
        this.on('change:datas', () => this.trigger('change:script'));
      },
   },
   // ...
});
artf commented 3 years ago

If you add datas in script-props the script should be updated automatically. I guess you're not binding properly the textarea event. You just need to update the datas prop in your onEvent callback

// by default, onEvent is triggered on any `change` event
onEvent({ elInput, component, event }) {
  const txtArea = elInput.querySelector('textarea');
  txtArea && component.set('datas', txtArea.value);
}

PS: I see that you're using model: defaultModel.extend({ in the wrong way. It's an old API to define custom components, don't use it as it has a lot of drawbacks, refer to this guide about the current API https://grapesjs.com/docs/modules/Components.html

imouou commented 3 years ago

If you add datas in script-props the script should be updated automatically. I guess you're not binding properly the textarea event. You just need to update the datas prop in your onEvent callback

// by default, onEvent is triggered on any `change` event
onEvent({ elInput, component, event }) {
  const txtArea = elInput.querySelector('textarea');
  txtArea && component.set('datas', txtArea.value);
}

PS: I see that you're using model: defaultModel.extend({ in the wrong way. It's an old API to define custom components, don't use it as it has a lot of drawbacks, refer to this guide about the current API https://grapesjs.com/docs/modules/Components.html

Thanks @artf and @Ju99ernaut, It is worked.

`model: defaultModel.extend... I copied this code from other plugins, I will correct it, thank you again.