Is it possible to do constructor injection for lit element service from app consuming the lit element service

450 Views Asked by At

I am new to web-component and lit elements. I wanted to see if its possible to inject values from client class to web-component service through constructor injection, like we do in angular spa applications.

I have created a simple lit element bundle file using rollup.config.js. This bundle file is uploaded in Netstorage. I am currently trying to figure out if it's possible to do constructor injection of some values that is passed from the client service (angular spa component.ts constructor) that is consuming the lit element. My lit element is does not have a UI component and only has some functions to gather configs which I want to pass from the client app..

I am able to access the lit element service through the client app as follows:

index.html:
  <script type="module" src="https://<www.path-to-my-cdn-file>/my-lit-element.js”></script>
<my-lit-element></my-lit-element>

Now I can access the functions in the lit element class as :

export interface LitElement extends HTMLElement {
  testMethod():void;
}

declare global {
  interface HTMLElementTagNameMap {
    'my-lit-element': MyLitElement;
  }
}

@Injectable()
export class ClientService {

 
  constructor() { }

  testCDN() {
    const el = document.querySelector('dcf-smartweb-service');
    customElements.whenDefined('dcf-smartweb-service').then(async () => {
      
      //prints this method contained inside the cdn file
      el.testMethod();
   })
    }

}

my cdn lit-element file looks like this:

import {customElement} from "lit/decorators.js";
import {LitElement} from "lit";

@customElement('my-lit-element')
export class MyLitElement extends LitElement {

 constructor() {
    super();

    console.log('this is test log');

    const config : String = '';

 // want config value to come from injection from client’s ts file
    if (config != null || config != '') {
      console.log('inside config');
      console.log('config', config)
    }
    console.log('test log');
  }


  /**
   * invoked when a component is added to the document's DOM
   */
  connectedCallback() {
    super.connectedCallback();
  }

    testMethod() {
      console.log('Hi from testMethod()');
    }

}

declare global {
  interface HTMLElementTagNameMap {
    'my-lit-element': MyLitElement;
  }
}

I want to know can I pass value from the constructor of my typescript file (ClientService) to this cdn MyLitElement class's constructor.

Is there any other way (connected classbacks etc to pass values between client and lit element class)

Please advise

1

There are 1 best solutions below

0
Yevgeniy On

for constructor injection you must controll the lifecycle of your objects. AFAIK there is no construction injection in lit, because the constructor is called by the browser (not by the framework like for example in case of angular). You can implement dependency injection in Lit using Context. Your root component would create a instance of ClientService and provide it to components further down the DOM. It would look something like this:

const clientServiceContext = createContext("clientService")

connectedCallback() {
   super.connectedCallback();

   new ContextProvider(this, clientServiceContext, new ClientService())
}

and then you would inject the instance of ClientService in MyLitElement like this:

connectedCallback() {
   super.connectedCallback();

   new ContextConsumer(this, clientServiceContext, clientService => console.log("TODO: do something useful with clientService here."))
}

find out more about Context in Lit here: https://lit.dev/docs/data/context/