Data binding from slots?

140 Views Asked by At

I've been working with Lit and recently I got into a weird issue where I couldn't get the property change detection in updated lifecycle callback when the property value (in this case: myProperty) is changed for the component which is loaded via slot.

This is what I've been doing as an example:

parentComponent.ts

@property({ type: Object })
public myProperty: MediaStream;

constructor() {
  super();
  this.myProperty = new MediaStream();
}

triggerUpdate() {
  navigator.mediaDevices
    .getUserMedia({
      audio: true,
      video: true,
     })
    .then(async (stream) => {
      this.myProperty = stream;
    });
}

render() {
  return html`
    <child-component>
      <div slot="grand-child-slot">
        <grand-child-component
          .myProperty="${this.myProperty}"
        >
        </grand-child-component>
      </div>
    </child-component>
  `
}

grandChildComponent.ts

@property({ type: Object })
public myProperty: MediaStream;

updated(changedProperties) {
   super.updated(changedProperties);
   if (changedProperties.has('myProperty')) {
     console.log(`Property "myProperty" has been updated to: ${this.myProperty}`);
   }
 }

In the above example, the console.log never execute when the myProperty is updated to a new value.

If I reload the grand-child-component within the slot then it works. I would expect the change to happen real time without any reloading the template.

Does anybody has a clue why this happens when used within a slot?

1

There are 1 best solutions below

5
Chellappan வ On

If you declare class property in lit it will not trigger an update. However you can explicitly trigger update by calling requestUpdate

triggerUpdate() {
  this.someProp = true;
  this.requestUpdate()
}

or

Alternatively you can declare state reactive property that will trigger an update when it changes

@state() someProp = false;


triggerUpdate() {
  this.someProp = true;
}

render() {
  return html`
    <child-component>
      <div slot="grand-child-slot">
        <grand-child-component
          .hasUpdated="${this.hasUpdated}"
        >
        </grand-child-component>
      </div>
    </child-component>
  `
}

Update your hasUpdated props name to another name hence hasUpdated is reserved word in lit