<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Federico Giacomini</title>
    <description>The latest articles on DEV Community by Federico Giacomini (@crocsx).</description>
    <link>https://dev.to/crocsx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F198188%2F5af5fa17-6691-48df-993b-6afb16192d35.jpg</url>
      <title>DEV Community: Federico Giacomini</title>
      <link>https://dev.to/crocsx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/crocsx"/>
    <language>en</language>
    <item>
      <title>Track your NGRX Actions State</title>
      <dc:creator>Federico Giacomini</dc:creator>
      <pubDate>Tue, 28 Dec 2021 05:12:25 +0000</pubDate>
      <link>https://dev.to/crocsx/track-your-ngrx-actions-state-2if9</link>
      <guid>https://dev.to/crocsx/track-your-ngrx-actions-state-2if9</guid>
      <description>&lt;p&gt;In this article, I would like to propose a solution for handling the state of multiple actions inside your Ngrx store. I will assume you already know the basics of Ngrx or other Redux pattern-based state management tools and are also pretty familiar with Angular and Typescript, as I will go pretty quick on the details.&lt;/p&gt;

&lt;p&gt;One of the most common situations when using a reactive state management library is handling asynchronous API. The most common approach to tackling async operations is creating three actions for each possible outcome (request/success/failure) and making a side effect handling each of them. It is also common to have some flags in our state that track the store's current state. &lt;/p&gt;

&lt;p&gt;Here is a classic example in NGRX very similar to the one in the "example repository" :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;actions.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const userAddRequest = createAction(
  '[User] User Add Request',
  props&amp;lt;{username: string}&amp;gt;()
);

export const userAddSuccess= createAction(
  '[User] User Add Success',
  props&amp;lt;{username: string, id: number}&amp;gt;()
)

export const userAddFailure = createAction(
  '[User] User Add Failure',
  props&amp;lt;{message: string}&amp;gt;()
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;effect.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  userAddRequest$ = createEffect(() =&amp;gt;
    this.actions$.pipe(
      ofType(userActions.userAddRequest ),
      exhaustMap(({username}) =&amp;gt;
        this.userService.add({username}).pipe(
          map(response =&amp;gt; userActions.userAddSuccess(response)),
          catchError((error: any) =&amp;gt; of(userActions.userAddFailure(error))))
      )
    )
  );

  userAddSuccess$ = createEffect(
    () =&amp;gt;
      this.actions$.pipe(
        ofType(userActions.userAddSuccess),
        tap(() =&amp;gt; {
          alert('User Add Succeeded');
        })
      ),
    { dispatch: false }
  );

  userAddFailure$ = createEffect(
    () =&amp;gt;
      this.actions$.pipe(
        ofType(userActions.userAddFailure),
        tap(() =&amp;gt; {
          alert('User Add Failed');
        })
      ),
    { dispatch: false }
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;reducer.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface State {
  users: User[];
  isLoading: boolean;
  isLoadingSuccess: boolean;
  isLoadingFailure: boolean;
}

const reducer = createReducer(
  initialState,
  on(userActions.userAddRequest, (state) =&amp;gt; ({isLoading: true})),
  on(userActions.userAddSuccess, (state, {user}) =&amp;gt; ({users: state.users.concat(user) , isLoading: false, isLoadingSuccess: true})),
  on(userActions.userAddFailure, (state, {user}) =&amp;gt; ({user, isLoading: false, isLoadingFailure: true})),
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;selector.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const getLoaded = (state: State) =&amp;gt; state.isLoadingSuccess;
export const getLoading = (state: State) =&amp;gt; state.isLoading;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works nicely in many scenarios, but I found this approach to be fairly limited when we would like to give more advanced feedbacks to users.&lt;/p&gt;

&lt;p&gt;Let's imagine the following UI : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UoKMo936--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzi6nfhcmtl2p40dob79.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UoKMo936--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzi6nfhcmtl2p40dob79.jpg" alt="Example UI" title="Example UI" width="721" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have a list of users on the left and a form to create a user on the right. This page effectuates three operations on our User Store :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getUsers&lt;/code&gt;&lt;br&gt;
&lt;code&gt;deleteUser&lt;/code&gt;&lt;br&gt;
&lt;code&gt;createUser&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Out of those three operations, we would like to display a specific loader on the page :&lt;/p&gt;

&lt;p&gt;When users are being loaded, we would like to show a loader on the list.&lt;br&gt;
When a user is being deleted, we would like to show &lt;br&gt;
a loader ONLY on the user that is being deleted.&lt;br&gt;
When a user is being created, we would like to show &lt;br&gt;
a loader on the Create Button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gC5erssa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydjd54bkjdfmxp0q10f5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gC5erssa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydjd54bkjdfmxp0q10f5.jpg" alt="Example Loading UI" title="Example Loading UI" width="880" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A single flag would not work correctly since all those operations are contained in the same store module. We would have to set a flag for each operation inside the store or add some variable in our component to hold which process is currently executed.&lt;/p&gt;

&lt;p&gt;But this is troublesome and would add a lot of logic; what if we could track the state of each Action independently?&lt;/p&gt;
&lt;h2&gt;
  
  
  Tracking The State of any NGRx Action
&lt;/h2&gt;

&lt;p&gt;To make things easier, we can create a unique &lt;code&gt;loader&lt;/code&gt; store in our application that we use for the single purpose of tracking actions and their state. It allows us to track the current state of any dispatched Ngrx action that we wish to follow.&lt;/p&gt;

&lt;p&gt;First, we replaced the booleans flags with a simple enum instead. It is quicker to change a single property and less prone to situations where a flag is forgotten in a wrong state like &lt;code&gt;{isLoading: true, isSucceded: true}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export enum ActionState {
  LOADING = 'LOADING',
  SUCCEEDED = 'SUCCEEDED',
  FAILED = 'FAILED',
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, the idea is to consider "async" actions as a single &lt;code&gt;set&lt;/code&gt;. Each Action in a &lt;code&gt;set&lt;/code&gt;  would share a key with others, and we would use it to update the state of that operation in our &lt;code&gt;loaders&lt;/code&gt; store.&lt;/p&gt;

&lt;p&gt;One way to do this is to create a wrapper over our Actions using &lt;a href="https://ngrx.io/api/store/createAction#usage-notes"&gt;&lt;code&gt;createAction with method&lt;/code&gt;&lt;/a&gt;. It will allow us to add some &lt;code&gt;metadata&lt;/code&gt; alongside the Action definition. This &lt;code&gt;metadata&lt;/code&gt; can be anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const userAddSetkey = '[User] User Add Key';
export const userAddRequest = createAction(
  '[User] User Add Request',
  function prepare(payload: {username: string, password: string}) {
    return withLoader({ [userAddSetkey]: ActionState.LOADING }, payload);
  }
);
export const userAddSuccess = createAction(
  '[User] User Add Success',
  function prepare() {
    return withLoader({ [userAddSetkey]: ActionState.SUCCEEDED }, null);
  }
);
export const userAddFailure = createAction(
  '[User] User Add Failure',
  function prepare(payload: { message: string }) {
    return withLoader({ [userAddSetkey]: ActionState.FAILED }, payload);
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can assign an anonymous function; we went with &lt;code&gt;prepare&lt;/code&gt; because it is more similar to the &lt;a href="//createAction%20%7C%20Redux%20Toolkit%20(redux-toolkit.js.org)"&gt;&lt;code&gt;redux prepare&lt;/code&gt;&lt;/a&gt;. This function adds additional information to the payload and the actions when they are initialized.&lt;/p&gt;

&lt;p&gt;As you may note, we also wrote a simple wrapper &lt;code&gt;withLoader&lt;/code&gt; around our payload. This method will add a property key that will be the same for each Action in our application that implements the tracking. That property will be helpful to know if the dispatched Action contained a state tracker or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const LOADER_KEY = '@ngrx-custom-loader';

export type WithLoader&amp;lt;T&amp;gt; = T &amp;amp; {
  [LOADER_KEY]: { [k: string]: ActionState };
};

export function withLoader&amp;lt;T&amp;gt;(loader: Partial&amp;lt;{ [k: string]: ActionState }&amp;gt;, payload?: T) {
  return Object.assign(payload || {}, { [LOADER_KEY]: loader }) as WithLoader&amp;lt;T&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When creating Action using &lt;code&gt;withLoader&lt;/code&gt;, we will access a new property alongside &lt;code&gt;type&lt;/code&gt; and &lt;code&gt;payload&lt;/code&gt; that will store the &lt;code&gt;action&lt;/code&gt; key and the &lt;code&gt;state&lt;/code&gt;. We define this new Action structure as &lt;code&gt;WithLoader&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;if you now log an action that implements the above structure, it will result like the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {
        @ngrx-custom-loader: {'[User] User Add Key': 'LOADING'}
        type: "[User] User Add Request"
        payload: {username: 'jhon'}
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to make some use of those loader keys. We implemented a &lt;code&gt;loader&lt;/code&gt; store that will save the &lt;code&gt;state&lt;/code&gt; of all actions implementing &lt;code&gt;withLoader&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;state.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface State {
  actionState: Record&amp;lt;string, ActionState&amp;gt;;
}

export interface LoadersPartialState {
  readonly [LOADERS_FEATURE_KEY]: State;
}

export const initialState: State = {
  actionState: {},
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It starts empty &lt;code&gt;{}&lt;/code&gt; and will grow every time an action is dispatched to look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    '[Login] Login Key': 'SUCCEEDED',
    '[User] User Add Request': 'LOADING',
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our reducer will check if the current Action contains our custom property &lt;code&gt;LOADER_KEY&lt;/code&gt; assigned above. If yes, we will store this action state; else, it will do nothing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reducer.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function reducer(
  state: State | undefined = initialState,
  action: Action | WithLoader&amp;lt;Action&amp;gt;
) {
  if (Object.prototype.hasOwnProperty.call(action, LOADER_KEY)) {
    const loader = (action as WithLoader&amp;lt;Action&amp;gt;)[LOADER_KEY];
    return {
      ...state,
      actionState: {
        ...state.actionState,
        ...loader,
      },
    };
  }
  return state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And last, the selector will check the store content and return the state of a specific action. We can pass an array of Actions that we would like to know the state, and it will return a boolean if any of them is currently loading. You can implement the same for Failure, Success, etc., or just one that would give back the state. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;selector.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const getIsLoading = (actions: string[] = []) =&amp;gt;
  createSelector(getLoadersState, (state) =&amp;gt; {
    if (actions.length === 1) {
      return state.actionState[actions[0]] === ActionState.LOADING;
    }
    return actions.some((action) =&amp;gt; {
      return state.actionState[action] === ActionState.LOADING;
    });
});

// We added an additional state INIT used when the operation has never been called. 
export const getLoadingState = (action: string) =&amp;gt;
  createSelector(
    getLoadersState,
    (state) =&amp;gt; state.actionState?.[action] || ActionState.INIT;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's use our tracking system :&lt;/p&gt;

&lt;p&gt;We can now quickly implement our previous UI requirement :&lt;/p&gt;

&lt;p&gt;assuming you create all Actions correctly, we can do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // The user are getting loaded
    this.store.dispatch(loadUsersList());
    this.usersLoading$ = this.store.pipe(
      select(getIsLoading([userListLoadSetKey]))
    );

    // A user is being delete
    // for this case you also need to store what user it getting deleted to show the feedback on the correct row.
    InDeletionUserId = userId;
    this.store.dispatch(deleteUser({ id: userId }));
    this.userDeleting$ = this.store.pipe(
      select(getIsLoading([userDeleteSetKey]))
    );

    // A user is being created
    this.store.dispatch(createUser({ id: accountId }));
    this.userCreating$ = this.store.pipe(
      select(getIsLoading([userAddSetKey]))
    );

    // Any of the above is loading
    this.isUserStoreLoading$ = this.store.pipe(
      select(
        getIsLoading([userListLoadSetKey, userDeleteSetKey, userAddSetKey])
      )
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;getLoadingState&lt;/code&gt;, you can also track when an operation is finished; helpful in those rare cases where you would like to execute a side effect to Actions outside of an NGRx effect. For example, reset a form when a user is created :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  onSubmit() {
    this.form.controls.username.disable();
    this.store.dispatch(userAddRequest({ ...this.form.getRawValue() }));

    this.store
      .pipe(select(getLoadingState([userAddSetKey])))
      .pipe(
        takeWhile(
          (state) =&amp;gt;
            ![ActionState.SUCCEEDED, ActionState.FAILED].includes(state),
          true
        ),
        filter((state) =&amp;gt; state === ActionState.SUCCEEDED),
        tap(() =&amp;gt; this.form.controls.username.enable())
      )
      .subscribe();
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find a demo of this approach on the following &lt;a href="https://stackblitz.com/edit/angular-ivy-cb5qv3?file=src/app/app.component.html"&gt;Stackblitz&lt;/a&gt; or &lt;a href="https://github.com/Crocsx/dev.to/tree/main/blog-posts/track-your-ngrx-actions-state/exemple/demo-app"&gt;Repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/angular-ivy-cb5qv3?embed=1&amp;amp;&amp;amp;" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I hope I didn't go too fast and that this post was helpful. It works very fine on our project, but we might have overlooked some behaviors. One central flaw point that I didn't cover is clearing the loaders once in a while (on route navigation, for example) to avoid storing gigantic objects in your NGRx store. But this is only problematic if your project contains a lot of Action, and we currently only have 150 actions. Please feel free to comment and give feedback on such an approach. Also, do not hesitate to ask for clarification or points I passed over too quickly. &lt;/p&gt;

&lt;p&gt;Thank you, and see you in the next post!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ngrx</category>
      <category>angular</category>
      <category>redux</category>
    </item>
    <item>
      <title>Share Components across Front Ends frameworks using Nx and Web Components - Part 3</title>
      <dc:creator>Federico Giacomini</dc:creator>
      <pubDate>Sat, 13 Nov 2021 03:19:00 +0000</pubDate>
      <link>https://dev.to/crocsx/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-3-4ndp</link>
      <guid>https://dev.to/crocsx/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-3-4ndp</guid>
      <description>&lt;p&gt;This is the third of a three parts Guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components"&gt;Part 1 - Project Setup and Introduction to Web Component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-2"&gt;Part 2 - Add Custom Style and Property Binding&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-3"&gt;Part 3 - Output Event and Allow Retrocompatibility.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Part 3 - Output Event and Allow Retrocompatibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In part one, we introduced Web Components, what they are and how to use them. We also created and set up an Nx workspace with an Angular and React project alongside a shared Web Components library. We created a custom element that "listens" to the attribute &lt;code&gt;title&lt;/code&gt; and changed the &lt;code&gt;DOM&lt;/code&gt; content accordingly. The second part added some custom styles and showed how to pass complex objects via attribute and property. &lt;br&gt;
This final section will focus on Events and listening to them in our app and Polyfill to allow our web component to work on old browsers.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Dispatch and receive Events
&lt;/h3&gt;

&lt;p&gt;If you follow the previous three parts, you should already have your monorepo setup with your shared library and the Angular and React app ready. We are going to create a new shared Web Component to showcase events. A simple counter that increments on button click and dispatches an event with the current value outside of the component.&lt;/p&gt;

&lt;p&gt;let's start with the template, nothing new here :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const template = document.createElement('template');
template.innerHTML = `&amp;lt;style&amp;gt;
    #count {
      color: red;
    }
  &amp;lt;/style&amp;gt;
  &amp;lt;p&amp;gt;button clicked &amp;lt;span id="count"&amp;gt;0&amp;lt;/span&amp;gt; times&amp;lt;/p&amp;gt;
  &amp;lt;button id="btCounter"&amp;gt;Click Here&amp;lt;/button&amp;gt;`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create the component code, a counter with an optional initial value, which will increment according to each button click. There is nothing new here :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoCounterElement extends HTMLElement {
  private _count = 0;
  get count(): number {
    return this._count;
  }

  set count(val: number) {
    this._count = val
    this.update(this._count);
  }

  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.appendChild(template.content.cloneNode(true));
    this.shadowRoot.getElementById('btCounter').onclick = () =&amp;gt; this.increment();
  }

  increment() {
    this.update(++this.count);
  }

  update(count: number) {
    this.shadowRoot.getElementById('count').innerHTML = count.toString();
  }
}

customElements.define('demo-counter', DemoCounterElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Export this component from your library (remember it's the &lt;code&gt;index.ts&lt;/code&gt;) and import it in Angular and react :&lt;/p&gt;

&lt;p&gt;In our Angular component template (we start counting from 1):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-counter [count]="3"&amp;gt;&amp;lt;/demo-counter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in our React component (we start counting from 2):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function App() {
  const counter = useRef&amp;lt;DemoCounterElement&amp;gt;(null);

  useEffect(function () {
    if(counter.current) {
      counter.current.count = 2;
    }
  }, []);

  return (
    &amp;lt;div className={styles.app}&amp;gt;
      &amp;lt;demo-counter ref={counter} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you start both apps, it will already increment the counter on each click, but we would like to get notified outside of our Web Components when users click the button. To do this, we will need to dispatch a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent"&gt;Custom Event&lt;/a&gt; from our Web Component and listen to it in our apps. Custom Event is an interface representing events initialized by an application for any purpose.&lt;/p&gt;

&lt;p&gt;In our Web Component &lt;code&gt;increment&lt;/code&gt; method, let's create and dispatch a new custom Event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  increment() {
    this.update(++this.count);
    this.dispatchEvent(new CustomEvent&amp;lt;{ count: number }&amp;gt;('incremented', {detail: { count: this.count }}));
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;detail&lt;/code&gt; to pass any data we would like to share from this event. &lt;code&gt;detail&lt;/code&gt; will be &lt;code&gt;readonly&lt;/code&gt; once the event is initialized.&lt;/p&gt;

&lt;p&gt;With this simple change, let's update our Angular and React to log the event in the console.&lt;/p&gt;

&lt;p&gt;In Angular template, we can now bind the event :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-counter [count]="3" (incremented)="clicked($event)"&amp;gt;&amp;lt;/demo-counter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and in the component code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  clicked(event: Event) {
    console.log(event)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--muISZsOf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dj50w3q7q02ukvzz0io6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--muISZsOf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dj50w3q7q02ukvzz0io6.gif" alt="Show Angular Log" title="Show Angular Log" width="880" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For React, things are not as simple. Our event is not a native one, and there is currently no simple way (as far as I know) to listen to that event directly from the template. You will either need an additional library like &lt;a href="https://github.com/pengzhanlee/xeact"&gt;xeact&lt;/a&gt; or use the &lt;code&gt;ref&lt;/code&gt; as we did for the properties. There are several issues in the React repository asking for easier management of custom events, but none have been implemented yet.&lt;/p&gt;

&lt;p&gt;So we will use the &lt;code&gt;useRef&lt;/code&gt; hook and the &lt;code&gt;useEffect&lt;/code&gt; to add and remove our listeners.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function App() {
  let eventRef: DemoCounterElement;
  const counter = useRef&amp;lt;DemoCounterElement&amp;gt;(null);

  const onIncrement = (e) =&amp;gt; {
    console.log(e)
  }

  useEffect(() =&amp;gt; {
    const counterRef = counter.current; 
    if(counterRef) {
      counterRef.count = 2
      counterRef.addEventListener('incremented', onIncrement)
    }
    return () =&amp;gt; {
      if(counterRef) {
        counterRef.removeEventListener('incremented', onIncrement)
      }
    }
  })


  return (
    &amp;lt;div className={styles.app}&amp;gt;
      &amp;lt;demo-counter ref={counter}/&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fire your app up again and check your console. Your log should appear in your React app. &lt;/p&gt;

&lt;p&gt;Great, now you can pass attributes, properties and dispatch custom events from your Web Components! One last thing is left for us, adding Polyfill to make them compatibles with old browsers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pk7jZWC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gdhmp07g9hvagammv49.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pk7jZWC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gdhmp07g9hvagammv49.gif" alt="Show React Log" title="Show React Log" width="880" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  2 Add Polyfill
&lt;/h1&gt;

&lt;p&gt;To ensure compatibility with older browsers, it is necessary to include a Web Components polyfills. Now, this is not a requirement, and it is OK only to target new browsers. The choice is up to you and your needs. As Angular says, "polyfills cannot magically transform an old, slow browser into a modern, fast one.", and the latest Angular 13 recently dropped support for IE11.&lt;/p&gt;

&lt;p&gt;If you wish to allow an old browser to use your app, you will need to set up some polyfill to add additional code to the page and not break modern features that were not available before. Angular and React do not come with a specific polyfill for web components; we will have to add one manually. Luckily, there is a pretty popular repository that will do everything for us. &lt;/p&gt;

&lt;p&gt;In your project, install &lt;a href="https://github.com/webcomponents/polyfills"&gt;&lt;code&gt;@webcomponents/webcomponentsjs&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save @webcomponents/webcomponentsjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now must load our Polyfill in Angular and React. For this feature, both frameworks work similarly.&lt;/p&gt;

&lt;p&gt;Angular and React come with a file named &lt;code&gt;polyfill.ts&lt;/code&gt;, which you will find in both projects &lt;code&gt;src&lt;/code&gt; folders. We can add our Polyfill inside the file directly, and it will be loaded on pre es5 browsers.&lt;/p&gt;

&lt;p&gt;Be sure to use the correct path.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;polyfill.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; import "@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"
 import "@webcomponents/webcomponentsjs/webcomponents-loader.js"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be ready to go. You will need an old machine or a VM to test this or some testing service like &lt;a href="https://app.lambdatest.com/console/realtime"&gt;lambdatest&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  3 Conclusion
&lt;/h1&gt;

&lt;p&gt;That is it for this series. You can now create your fully customized HTML elements and use them across various projects. While Web Components are not replacing current frameworks, they can be a great tool to complete them for things like shared UI library. I hope you learned something and that you enjoyed my firsts ever blog post series. &lt;br&gt;
Thank You!&lt;/p&gt;

&lt;p&gt;You can find the entire repo here :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Crocsx/dev.to/tree/main/blog-posts/share-component-across-front-end-framework-using-nx-and-web-component/exemple/demo-shared"&gt;https://github.com/Crocsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found a Typo or some problem?&lt;/p&gt;

&lt;p&gt;If you’ve found a typo, a sentence that could be improved, or anything else that should be updated on this blog post, you can access it through a git repository and make a pull request. Please go directly to &lt;a href="https://github.com/Crocsx/dev.to"&gt;https://github.com/Crocsx/dev.to&lt;/a&gt; and open a new pull request with your changes.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webcomponents</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Share Components across Front Ends frameworks using Nx and Web Components Part 2</title>
      <dc:creator>Federico Giacomini</dc:creator>
      <pubDate>Thu, 28 Oct 2021 06:22:52 +0000</pubDate>
      <link>https://dev.to/crocsx/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-2-4e5d</link>
      <guid>https://dev.to/crocsx/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-2-4e5d</guid>
      <description>&lt;p&gt;This is the second of three Part Guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components"&gt;Part 1 - Project Setup and Introduction to Web Component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-2"&gt;Part 2 - Add Custom Style and Property Binding&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-3"&gt;Part 3 - Output Event and Allow Retrocompatibility.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Part 2 - Add Custom Style and Property Binding
&lt;/h2&gt;

&lt;p&gt;In part one, we introduced Web Components, what they are and how to use them. We also created and set up an Nx workspace with an Angular and React project alongside a shared Web Components library. We created a custom element that "listens" to the attribute &lt;code&gt;title&lt;/code&gt; and changed the &lt;code&gt;DOM&lt;/code&gt; content accordingly. In this second part, we are going further by styling and assigning properties to our Web Components.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Style our Web Component
&lt;/h3&gt;

&lt;p&gt;Our Web Component works, but they are very flat at the moment. It would be great to add some CSS to it. You may want to add a CSS class to our title and create a global stylesheet with some rules, and it would work. But the idea behind Web Components is creating fully independent elements that are auto-sufficient and do not require anything from the "outside". Adding a global CSS class would affect every element on our page and quickly turn into a gigantic file full of rules.&lt;/p&gt;

&lt;p&gt;Hopefully, Web Components allow us to use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM"&gt;Shadow DOM&lt;/a&gt;, which makes us able to keep the markup structure, style, and behavior hidden and separate from other code on the page. Thanks to it, elements will not clash, and the code will be kept simple and clean.&lt;/p&gt;

&lt;p&gt;Let's head back to our library (set up in part one) and edit our title component (or create a new title element).&lt;/p&gt;

&lt;p&gt;If you still have what we worked on, it should look like this (I removed the logs) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoTitleElement extends HTMLElement {
    public static observedAttributes = ['title'];

    attributeChangedCallback(name: string, old: string, value: string) {
      this.innerHTML = `&amp;lt;h1&amp;gt;Welcome From ${this.title}!&amp;lt;/h1&amp;gt;`;
    }
}

customElements.define('demo-title', DemoTitleElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we just replaced the entire HTML inside our element for every update on our attribute &lt;code&gt;title&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    attributeChangedCallback(name: string, old: string, value: string) {
      this.innerHTML = `&amp;lt;h1&amp;gt;Welcome From ${this.title}!&amp;lt;/h1&amp;gt;`;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may know, this method doesn't allow us to append some &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag. Therefore, we are unable to create new styles unless we manually write a class and add some global rules. Also, this approach is pretty poor in performance, as we recreate all the content for every change of our attribute. It would be great to have some kind of template... &lt;/p&gt;

&lt;p&gt;Well, it turns out there is &lt;a href="//Using%20templates%20and%20slots%20-%20Web%20Components%20%7C%20MDN%20(mozilla.org)"&gt;template&lt;/a&gt; element that would suit our need! Templates are not rendered in the DOM, but can still be referenced via Javascript. We can then clone this template inside our Shadow DOM once and access it across our components. &lt;/p&gt;

&lt;p&gt;Let's create one outside of our component class and assign the styles we like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const template = document.createElement('template');
template.innerHTML = `&amp;lt;style&amp;gt;
    h1 {
      color: red;
    }
  &amp;lt;/style&amp;gt;
  &amp;lt;h1&amp;gt;Welcome From &amp;lt;span id="title"&amp;gt;&amp;lt;/span&amp;gt;!&amp;lt;/h1&amp;gt;`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice I added a &lt;code&gt;span&lt;/code&gt; with an &lt;code&gt;id&lt;/code&gt; where we would like to write the dynamic title. It will come in handy for updating our DOM without having to recreate the template entirely.  &lt;/p&gt;

&lt;p&gt;Now in our Component &lt;code&gt;constructor&lt;/code&gt;, attach a Shadow DOM, and append our template to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoTitleColoredElement extends HTMLElement {
    public static observedAttributes = ['title'];

    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(template.content.cloneNode(true));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what we added &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;super&lt;/code&gt; will call the &lt;code&gt;constructor&lt;/code&gt; of &lt;code&gt;HTMLElement&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;attachShadow&lt;/code&gt;attaches a shadow DOM tree to the specified element and returns a reference to its ShadowRoot. There can be two different &lt;code&gt;encapsulation modes&lt;/code&gt;. &lt;code&gt;open&lt;/code&gt; means elements of the shadow root are accessible from JavaScript outside the root while &lt;code&gt;closed&lt;/code&gt; Denies access to the node(s) of a closed shadow root from JavaScript outside&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;this.shadowRoot.appendChild&lt;/code&gt; we are adding our template to the shadow Root and using &lt;code&gt;template.content.cloneNode(true)&lt;/code&gt; we are cloning all the DOM element we defined in the template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, this is much better; our template is cloned once and will be available through &lt;code&gt;shadowRoot&lt;/code&gt; inside the component. &lt;/p&gt;

&lt;p&gt;When the attribute change, we can now update what interests us inside the template. As we only care about the &lt;code&gt;title&lt;/code&gt; attribute, we can simply add the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    attributeChangedCallback() {
      this.shadowRoot.getElementById('title').innerHTML = this.title;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should end up with a component similar to this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const template = document.createElement('template');
template.innerHTML = `&amp;lt;style&amp;gt;
    h1 {
      color: red;
    }
  &amp;lt;/style&amp;gt;
  &amp;lt;h1&amp;gt;Welcome From &amp;lt;span id="title"&amp;gt;&amp;lt;/span&amp;gt;!&amp;lt;/h1&amp;gt;`;

export class DemoTitleColoredElement extends HTMLElement {
    public static observedAttributes = ['title'];

    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(template.content.cloneNode(true));
    }

    attributeChangedCallback() {
      this.shadowRoot.getElementById('title').innerHTML = this.title;
    }
}

customElements.define('demo-title-colored', DemoTitleColoredElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice! Remember to add this new element to your library's export and try it on your Angular and/or React project. I added the old title we created previously and the new one on the bottom. What we expect to see is our old title to remain Black, while our new title should be Red (and do not affect &lt;code&gt;h1&lt;/code&gt; outside of it)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-title [title]="'Angular'"&amp;gt;&amp;lt;/demo-title&amp;gt;
&amp;lt;demo-title-colored [title]="'Angular'"&amp;gt;&amp;lt;/demo-title-colored&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6KRipF7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukfeivmufx3a45rn5v7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6KRipF7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukfeivmufx3a45rn5v7d.png" alt="Angular Red Black Title" title="Angular Red Black Title" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWESOME! Our style is applied only to our Component!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Passing object to Web Components
&lt;/h2&gt;

&lt;p&gt;One common thing we would like to do is pass objects to our Web Component, and not just simple strings.&lt;/p&gt;

&lt;p&gt;Since Web Component &lt;code&gt;attributeChangedCallback&lt;/code&gt; and &lt;code&gt;observedAttributes&lt;/code&gt; works exclusively with &lt;code&gt;attribute&lt;/code&gt;, a possible solution would be to stringify objects and pass them via the attribute &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes"&gt;&lt;code&gt;data-*&lt;/code&gt;&lt;/a&gt; and our HTML would remain valid.&lt;/p&gt;

&lt;p&gt;Let's try this first, we are going to pass a person &lt;code&gt;object&lt;/code&gt; to our Web Component and simply display that person's name.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Passing objects via attributes
&lt;/h3&gt;

&lt;p&gt;In our library, create a new element that will observe a custom attribute named &lt;code&gt;data-person&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoObjectElement extends HTMLElement {
    public static observedAttributes = ['data-person'];

    attributeChangedCallback(name: string, old: string, value: string) {
      console.log(`Attribute ${name} value:`, value);
    }
}

customElements.define('demo-object', DemoObjectElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this new element to your library's exports, and let's first use it in Angular.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;app.component.ts&lt;/code&gt; create this object :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  person = {
    firstName: 'Jack',
    lastName: 'Doe'
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move to the &lt;code&gt;app.component.html&lt;/code&gt; add and assign our object to our web component. You have to specify Angular to use &lt;code&gt;attribute&lt;/code&gt; by prefixing our binding with &lt;code&gt;attr.person&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-object [attr.data-person]="person"&amp;gt;&amp;lt;/demo-object&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see that our Web Component log will look like this : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Attribute data-person value: [object Object]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which is not what we want... To receive the entire object, we will need to use &lt;code&gt;JSON.stringify&lt;/code&gt; first and then &lt;code&gt;JSON.parse&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;Update our Angular &lt;code&gt;app.component.ts&lt;/code&gt; with the following line :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JSON = JSON;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-object [data-person]="JSON.stringify(person)"&amp;gt;&amp;lt;/demo-object&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also update our Web Component log to display the value as an &lt;code&gt;object&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(`Attribute ${name} value:`, JSON.parse(value));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will now display our object as expected : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Attribute data-person value: {"firstName":"Jack","lastName":"Doe"}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For React, it is very similar. Open &lt;code&gt;app.tsx&lt;/code&gt; and just add the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  return (
    &amp;lt;div className={styles.app}&amp;gt;
      &amp;lt;demo-object dataPerson={JSON.stringify(person)}/&amp;gt;/&amp;gt;
    &amp;lt;/div&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since our Web Components are "natives" HTML elements, just assigning &lt;code&gt;dataPerson&lt;/code&gt; will change the attribute &lt;code&gt;data-person&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Passing objects as attributes is enough in some cases where we just want to assign small objects. But ideally, we do not wish to pollute attributes, and worst, assign objects that will need to be stringified and parsed at every change. What about passing things as properties instead? Well, we can, but it is a bit harder. &lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Passing Object via Properties
&lt;/h3&gt;

&lt;p&gt;To allow our Web Component to receive properties, we first need to change a few things in the code. Web Components lifecycle works with &lt;code&gt;attributes&lt;/code&gt; so we are required to manually detect property changes, and call our method ourselves. Additionally, as stated in the last part, Web Components are consumed like basic HTML, therefor passing property to HTML elements varies depending on the framework we use. &lt;/p&gt;

&lt;p&gt;While we are at changes, let's also display the person's name and not just log it. Create a template in our component to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const template = document.createElement('template');
template.innerHTML = `
&amp;lt;style&amp;gt;
    .name {
        font-weight: bold;
    }
&amp;lt;/style&amp;gt;
&amp;lt;p&amp;gt;
    &amp;lt;span class="name"&amp;gt;first name&amp;lt;/span&amp;gt;
    &amp;lt;span id="firstName"&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
    &amp;lt;span class="name"&amp;gt;last name&amp;lt;/span&amp;gt;
    &amp;lt;span id="lastName"&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/p&amp;gt;`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now change our component code.  Assuming I would like to pass a property named &lt;code&gt;person&lt;/code&gt; to my Web Component. If we do all like we are used to doing until now, we would be doing the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoProfileElement extends HTMLElement {
    public static observedAttributes = ['person'];

    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(template.content.cloneNode(true));
    }

    attributeChangedCallback() {
      this.update(this.person);
    }

    update(person: {firstName: string, lastName: string}) {
      this.shadowRoot.getElementById('firstName').innerHTML = person.firstName;
      this.shadowRoot.getElementById('lastName').innerHTML = person.lastName;
    }
  }

  customElements.define('demo-profile', DemoProfileElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But as your Typescript might tell, &lt;code&gt;person&lt;/code&gt; is not an HTML attribute, so &lt;code&gt;this.person&lt;/code&gt; is not defined. Additionally, the &lt;code&gt;attributeChangedCallback&lt;/code&gt; will never be called since &lt;code&gt;observedAttributes = ['person'];&lt;/code&gt; can't observe attributes that do not exist.&lt;/p&gt;

&lt;p&gt;To fix this and make it work, we need to forget about what we did until now and implement our way to detect changes, like if we were coding a simple Typescript Class. You can try to fix it by yourself or just scroll for the solution.&lt;/p&gt;

&lt;p&gt;We going to need a property in our class I chose &lt;code&gt;_person&lt;/code&gt;, and a &lt;code&gt;get/set&lt;/code&gt; that will assign to that property&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoProfileElement extends HTMLElement {
    _person = {
      firstName: '',
      lastName: '',
  };

  get person(){
    return this._person
  }
  set person(value: {firstName: string, lastName: string}){
    this._person = value;
    this.update(this._person);
  }

  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }

    update(person: {firstName: string, lastName: string}) {
      this.shadowRoot.getElementById('firstName').innerHTML = person.firstName;
      this.shadowRoot.getElementById('lastName').innerHTML = person.lastName;
    }
}

customElements.define('demo-profile', DemoProfileElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, we just use a get/set to check when the property is updated and update our DOM accordingly.&lt;/p&gt;

&lt;p&gt;Let's try this in Angular, but before, don't forget to add this new element to your library's export!&lt;/p&gt;

&lt;p&gt;When passing Input to a component, Angular will assign it as a property of that element. It makes things simple for us, as we do not need to change much.&lt;/p&gt;

&lt;p&gt;In your Angular app, just add this line :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-profile [person]="person"&amp;gt;&amp;lt;/demo-profile&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QTn4hCwY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8g5c0cj6d7ag17lodemn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QTn4hCwY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8g5c0cj6d7ag17lodemn.png" alt="Angular With Profile Name" title="Angular With Profile Name" width="880" height="761"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's head to React, where things are a bit different. React pass props as JSX Attributes, and therefore, simply doing &lt;code&gt;&amp;lt;demo-profile person={person} /&amp;gt;&lt;/code&gt; will not work. We need to treat our Web Component as what it is, an HTML Element. So, get the reference and assign to it the property.&lt;/p&gt;

&lt;p&gt;In your React app, add a Reference to our component, and after initialization, assigns the &lt;code&gt;person&lt;/code&gt; property to our Web Component :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { DemoCounterElement, DemoProfileElement } from '@demo-shared/demo-library';

export function App() {
  const person = {
    firstName: 'Jack',
    lastName: 'Doe'
  }
  const profile = useRef&amp;lt;DemoProfileElement&amp;gt;(null);

  useEffect(function () {
    if(profile.current) {
      profile.current.person = person 
    }
  }, []);

  return (
    &amp;lt;div className={styles.app}&amp;gt;
      &amp;lt;demo-profile ref={counter}/&amp;gt;
    &amp;lt;/div&amp;gt;
  );

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all also for React; start the project, and you will see the same result!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0EU45vQO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/477d9r5nhecnqge3in83.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0EU45vQO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/477d9r5nhecnqge3in83.png" alt="React With Person Profile" title="React With Person Profile" width="880" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great, we did almost all we would like to do, but there are still some things we might want to add.&lt;br&gt;
In the last part, we will add some custom events to be dispatched in our Web Component and add polyfill to use our component on old browsers.&lt;/p&gt;

&lt;p&gt;You can find the entire repo here :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Crocsx/dev.to/tree/main/blog-posts/share-component-across-front-end-framework-using-nx-and-web-component/exemple/demo-shared"&gt;https://github.com/Crocsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found a Typo or some problem?&lt;/p&gt;

&lt;p&gt;If you’ve found a typo, a sentence that could be improved, or anything else that should be updated on this blog post, you can access it through a git repository and make a pull request. Please go directly to &lt;a href="https://github.com/Crocsx/dev.to"&gt;https://github.com/Crocsx/dev.to&lt;/a&gt; and open a new pull request with your changes.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nx</category>
      <category>webcomponents</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Share Components across Front Ends frameworks using Nx and Web Components - Part 1</title>
      <dc:creator>Federico Giacomini</dc:creator>
      <pubDate>Fri, 22 Oct 2021 05:57:08 +0000</pubDate>
      <link>https://dev.to/crocsx/share-components-across-front-ends-frameworks-using-nx-and-web-components-40jf</link>
      <guid>https://dev.to/crocsx/share-components-across-front-ends-frameworks-using-nx-and-web-components-40jf</guid>
      <description>&lt;p&gt;This is the first of a three parts Guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components" rel="noopener noreferrer"&gt;Part 1 - Project Setup and Introduction to Web Component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-2" rel="noopener noreferrer"&gt;Part 2 - Add Custom Style and Property Binding&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://crocsx.hashnode.dev/share-components-across-front-ends-frameworks-using-nx-and-web-components-part-3" rel="noopener noreferrer"&gt;Part 3 - Output Event and Allow Retrocompatibility.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Part 1 - Project Setup and Introduction to Web Component
&lt;/h2&gt;

&lt;p&gt;Today we are going to discover a way to share components across React and Angular projects using Nx and Web Components. We are going to set up a simple Monorepo project using NX, and utilize web components to share some simple UI elements across Angular and React. If you do not know about Nx and Monorepos, follow this introductive blog post : &lt;br&gt;
&lt;a href="https://crocsx.hashnode.dev/introduction-to-nx-and-monorepos" rel="noopener noreferrer"&gt;Introduction to NX and Monorepos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;### 1. What are web components?&lt;/p&gt;

&lt;p&gt;As developers, we all know that reusing code as much as possible is a good idea. But this has traditionally been hard for markup language like HTML, where repetition is often complicated to avoid. Nowadays, popular frameworks like React and Angular became a standard because they allow the reusability of templates and logic. Web Components aims to solve such problems and make it possible to develop framework-agnostic, custom components that use the HTML syntax. Modern browsers can natively interpret them without any third-party library.&lt;/p&gt;

&lt;p&gt;Now, this sounds great, why are we using React at all then? Well, Frameworks bring a lot more to the table than simple Web Components. &lt;br&gt;
State machines, routing, retro compatibility, etc... But Web Components can still be useful in some cases. Let's suppose we have a few applications in our company using different frameworks, that we would like to share some UI elements. Well, it would be nice to make a library of those elements that would work the same way independently of the framework used. Web Components can be a good choice for this.&lt;/p&gt;

&lt;p&gt;There is a lot of documentation about Web Components and I invite you to read some more in-depth posts about it : &lt;a href="https://kinsta.com/blog/web-components/#getting-started-with-web-components" rel="noopener noreferrer"&gt;A Complete Introduction to Web Components in 2021&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Create Our Workspace
&lt;/h3&gt;

&lt;p&gt;We are going to start by creating an Nx Monorepo, with two projects inside (one in Angular and one in React), and a library (using the &lt;a href="https://developers.google.com/web/fundamentals/web-components/customelements" rel="noopener noreferrer"&gt;Custom Element API&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;First, let's create an empty Nx workspace :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx --ignore-existing create-nx-workspace demo-shared --preset=empty&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Followed by an Angular and a React application, that you can name the way you want :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D @nrwl/angular
npx nx g @nrwl/angular:app demo-angular
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We install the angular "extension" for Nx, then create a project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D @nrwl/react
npx nx g @nrwl/react:app demo-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same here for react&lt;/p&gt;

&lt;p&gt;You will now see in your apps folder 4 new applications, the Angular + Angular e2e and React + React e2e. &lt;br&gt;
Great!&lt;/p&gt;

&lt;p&gt;We are ready to add the library where we will add our shared components, and use them athwart Angular and React.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx nx g @nrwl/workspace:lib demo-library&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ok, our workspace should be set up, and if you did it all correctly, your work tree should look something like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;demo-shared/
├── apps/
│   ├── demo-angular/
│   ├── demo-angular-e2e/
│   ├── demo-react/
│   └── demo-react-e2e/
├── libs/
│   └── demo-library
│       ├── src/
│       │   ├── lib/
│       │   └── index.ts
│       ├── jest.conf.js
│       ├── tsconfig.lib.json
│       ├── tsconfig.json
│       ├── tsconfig.spec.json
│       └── tslint.json
├── README.md
├── angular.json
├── nx.json
├── package.json
├── tools/
├── tsconfig.base.json
└── tslint.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking good? Great! Let's go to the next step, and start coding our shared component.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Shared Component using Web Components
&lt;/h3&gt;

&lt;p&gt;You are now ready to do some basic Web Components. Our opening example will be a simple component that displays a title using an &lt;code&gt;attribute&lt;/code&gt; and will change based on its value. &lt;/p&gt;

&lt;p&gt;Add a new folder and file inside the &lt;code&gt;lib&lt;/code&gt; folder :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;demo-title/demo-title.element.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And let's add some example code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class DemoTitleElement extends HTMLElement {
  public static observedAttributes = ['title'];

  connectedCallback() {
    console.log('Appended and connected to document')
  }

  disconnectedCallback() {
    console.log('Disconnected from document')
  }

  attributeChangedCallback(name: string, old: string, value: string) {
    console.log(`Element's attribute ${name} was ${old} and is now ${value}`);
    this.innerHTML = `&amp;lt;h1&amp;gt;Welcome From ${this.title}!&amp;lt;/h1&amp;gt;`;
  }
}

customElements.define('demo-title', DemoTitleElement);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quite a few things are available in the Web Components Lifecycle Methods :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;observedAttributes&lt;/code&gt;: Define the name of the &lt;code&gt;attributes&lt;/code&gt; that we will be able to bind as Input in React/Angular and receive updates in our Web Component Lifecycle method. In the above case, &lt;code&gt;title&lt;/code&gt; is a property that can be assigned when creating the component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;connectedCallback&lt;/code&gt;:  Invoked each time the custom element is appended and connected to the document's DOM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;disconnectedCallback&lt;/code&gt;: Invoked each time the custom element is disconnected to the document's DOM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;attributeChangedCallback&lt;/code&gt; Invoked each time that one of the &lt;code&gt;observedAttributes&lt;/code&gt; is changed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;customElements.define('demo-title', DemoTitleElement);&lt;/code&gt; Defines a new custom element, mapping the given name to the given constructor as an autonomous custom element.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is very important to note that Web Component &lt;code&gt;attributeChangedCallback&lt;/code&gt; works with &lt;code&gt;attributes&lt;/code&gt; and &lt;em&gt;NOT&lt;/em&gt; with &lt;code&gt;properties&lt;/code&gt;. To keep your HTML page valid, you should only use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes" rel="noopener noreferrer"&gt;valid HTML attributes&lt;/a&gt;. Attributes are also required to be plain strings, so objects will require to be &lt;code&gt;JSON.stringify&lt;/code&gt; first.&lt;br&gt;
If you would like to pass custom attributes, you should use the HTML markup [&lt;code&gt;data-*&lt;/code&gt;](&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*&lt;/a&gt;) and bind anything you want to it. &lt;br&gt;
In the second part of this post, we will discover a way to use properties instead, and bind any type of data. &lt;/p&gt;

&lt;p&gt;Ok, Before being able to use our Web Component, we must &lt;em&gt;NOT&lt;/em&gt; forget to add this element to our library's exports. Otherwise, we will not be able to import it, and we will break Nx cache and &lt;code&gt;affected&lt;/code&gt; commands (the useful Nx command that will build only modified projects and dependencies each time a file is changed)&lt;/p&gt;

&lt;p&gt;In your library folder, go to &lt;code&gt;index.ts&lt;/code&gt; and add the export line :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export * from './lib/demo-title/demo-title.element';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that our component is available outside of our library. Let's connect it with Angular and React, starting with Angular.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Setup Angular and React for Web Component
&lt;/h3&gt;
&lt;h4&gt;
  
  
  4.1 Setup Angular to use Web Component
&lt;/h4&gt;

&lt;p&gt;Inside your angular app, import the library, You can do it inside the &lt;code&gt;main.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '@demo-shared/demo-library'; // &amp;lt;-- our library

import { enableProdMode } from '@angular/core';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch((err) =&amp;gt; console.error(err));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we also need to register &lt;a href="https://angular.io/api/core/CUSTOM_ELEMENTS_SCHEMA" rel="noopener noreferrer"&gt;CUSTOM_ELEMENTS_SCHEMA&lt;/a&gt; in our app module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  bootstrap: [AppComponent],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this will tell the Angular compiler to refrain from throwing errors when seeing non-standard element tags in our templates.&lt;/p&gt;

&lt;p&gt;Finally, let's add the component to our app. Head to &lt;code&gt;app.component.html&lt;/code&gt; and just add our title component as if it was a normal Angular component. Remember, the component name is the one you chose previously inside the method &lt;code&gt;customElements.define&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.component.html&lt;/code&gt; should  be as simple as this after you removed the boilerplate HTML autogenerated by Nx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;demo-title [title]="'Angular'"&amp;gt;&amp;lt;/demo-title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the app :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx nx serve {angular app name}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and if all has been done correctly, you should see your component appearing with the Attribute you set!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcamu6zqt4lut9gr335t6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcamu6zqt4lut9gr335t6.png" title="Welcome Angular" alt="Welcome Angular"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2 Setup React to use Web Component
&lt;/h4&gt;

&lt;p&gt;Let's do the same with React :&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;main.tsx&lt;/code&gt; let's again import our library :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '@demo-shared/demo-library'; // &amp;lt;-- our library

import { StrictMode } from 'react';
import * as ReactDOM from 'react-dom';

import App from './app/app';

ReactDOM.render(
  &amp;lt;StrictMode&amp;gt;
    &amp;lt;App /&amp;gt;
  &amp;lt;/StrictMode&amp;gt;,
  document.getElementById('root')
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, same as in Angular, we need to tell React to allow components that are not defined within it. To allow this, we will need to create a type file on the root of the &lt;code&gt;src&lt;/code&gt; folder or the React project. Name it &lt;code&gt;intrinsic.d.ts&lt;/code&gt; and add inside the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;declare namespace JSX {
  interface IntrinsicElements {
    [elemName: string]: any;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add our component in React :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function App() {
  return (
    &amp;lt;div className={styles.app}&amp;gt;
      &amp;lt;demo-title title={"React"} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the React App, and you will see the same component but this time in React!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jg52vu3ip62oz7qoycd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jg52vu3ip62oz7qoycd.png" title="Welcome React" alt="Welcome React"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;br&gt;
/!\ If you have a warning about the webpack version, and your react app does not start, you can opt into webpack 5  &lt;code&gt;npx nx g @nrwl/web:webpack5&lt;/code&gt; and then serve the app again&lt;br&gt;
more &lt;a href="https://nx.dev/l/a/guides/webpack-5" rel="noopener noreferrer"&gt;Webpack 5 Migration&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Conclusion
&lt;/h3&gt;

&lt;p&gt;In this first part, we made a very simple Web Component and used it across our two different projects. There are many things to do with Web Components, you may have noticed that we only used &lt;code&gt;extends HTMLElement&lt;/code&gt;. But Web Components can extend and customize any HTML element. You could for example create your customized &lt;code&gt;HTMLVideoElements&lt;/code&gt; and use it in all the projects you want, even the ones in pure HTML/Javascript. &lt;a href="https://caniuse.com/?search=web%20components" rel="noopener noreferrer"&gt;Compatibility&lt;/a&gt; is still not perfect, But we will see how we can add polyfill to use our component on old browsers. Let's head to Part 2 where we going to customize our components and pass value using properties instead.&lt;/p&gt;

&lt;p&gt;You can find the full repo here :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Crocsx/dev.to/tree/main/blog-posts/share-component-across-front-end-framework-using-nx-and-web-component/exemple/demo-shared"&gt;https://github.com/Crocsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found a Typo or some problem?&lt;/p&gt;

&lt;p&gt;If you’ve found a typo, a sentence that could be improved, or anything else that should be updated on this blog post, you can access it through a git repository and make a pull request. Please go directly to &lt;a href="https://github.com/Crocsx/dev.to/tree/main/blog-posts/share-component-across-front-end-framework-using-nx-and-web-component/post.part1.md"&gt;https://github.com/Crocsx/dev.to&lt;/a&gt; and open a new pull request with your changes.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webcomponents</category>
      <category>nx</category>
      <category>angular</category>
    </item>
    <item>
      <title>Introduction to Nx and Monorepos</title>
      <dc:creator>Federico Giacomini</dc:creator>
      <pubDate>Fri, 01 Oct 2021 01:16:16 +0000</pubDate>
      <link>https://dev.to/crocsx/introduction-to-nx-and-monorepos-19c2</link>
      <guid>https://dev.to/crocsx/introduction-to-nx-and-monorepos-19c2</guid>
      <description>&lt;p&gt;Welcome to my blog post; this is Giacomini Federico. I work as a Front-end Developer for the &lt;a href="https://anymindgroup.com/products/anylogi/" rel="noopener noreferrer"&gt;AnyLogi&lt;/a&gt; team. Today I would like to introduce you to &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx&lt;/a&gt;, a “Smart, Extensible Build Framework” for building your Web Applications. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This post will go through the following points:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Quick introduction to Nx and Monorepos&lt;/li&gt;
&lt;li&gt;Why did we choose Nx for AnyLogi&lt;/li&gt;
&lt;li&gt;Create a simple Nx Monorepo&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. A Quick introduction to Nx and Monorepos
&lt;/h3&gt;

&lt;p&gt;Nx is a framework that allows you to architect, test, and build your project at any scale with the most popular modern Front-end frameworks like React and Angular and Back-end ones like NestJs or Express. To make this possible, Nx comes shipped with a large toolset that simplifies your Monorepo management. If you are unfamiliar with Monorepo, it is basically a version-controlled code repository that holds many projects and libraries. The Monorepo approach has several benefits over a common one. Here are a few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared code&lt;/strong&gt; - It is already possible with properly fragmented repositories to share common logic across the whole company, organization, or project. Monorepo makes it even easier to improve the DRY(ness) of your code as we can not just reuse common patterns, components, and types across different Front-end libraries but between Front-end and Back-end as well. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Atomic changes&lt;/strong&gt; - When making changes that would affect other projects/libraries (like an API definition), all those changes can be applied and tracked on a single branch/commit without having to track down all dependent projects and additional coordination efforts necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standardization&lt;/strong&gt; - It is easier to standardize code and tooling across the teams. You can impose branch policies to keep your main branch clean, limit access to specific branches, enforce naming guidelines, include code reviewers, and enforce best practices while sharing the same linter and prettier configurations on multiple projects and libraries in your repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Release management&lt;/strong&gt; - You can handle all your release pipelines once without having to set up over-complicated deployment sequences across repositories using a clear and defined flow that every team can follow and avoiding the deployment knowledge within each team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easier refactoring and dependencies&lt;/strong&gt; - Direct access to all micro-services makes refactoring the code in a Monorepo and changing the overall code structure much quicker than moving code between repositories. By updating the dependencies on the same repository, it is easier to avoid version conflicts between libraries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But why use Nx and not just create a simple angular or react workspace? What sets Nx apart is the extensive toolset that it brings to the table, helping you across all the facets of building your Monorepo. Here are some of the valuable features of Nx : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cached and Custom Operations&lt;/strong&gt; - Nx will allow you to define and cache operations avoiding the same code being built multiple times. When making changes to a library, you can automatically execute operations (like building, testing, linting, etc.) on affected projects, significantly reducing build times or pipeline executions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross framework components&lt;/strong&gt; - Another great feature coming with Nx is the possibility to build micro Front-ends and share the same component across React and Angular applications. You will code your component logic once and use it as is in your project. Additionally, all projects and libraries will be created with testing tools like Cypress, Storybook, and Jest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy to manage dependencies&lt;/strong&gt; - Nx also extends some eslint rules to allow you to carefully decouple and isolate your library and dependencies. With the tags system and dependencies tree, you can enforce the dependencies flow you like across your projects/libraries. Nx will help you find circular dependencies or dependencies that make no sense (for example, a library depending on a project). To have a quick glimpse of your project structure, you can generate a dependencies graph of the workspace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Configurable CLI&lt;/strong&gt; - Nx comes with a robust CLI that can be configured to work with different tools and even different languages providing commands to operate and manage all the chunks of your codebase. For example, If you are familiar with angular CLI, Nx will extend those commands to work with the whole NX Monorepo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Metadata-driven&lt;/strong&gt; - Everything in Nx comes with metadata to enable tool-ability. The default values, validations, auto-completion, and other settings are all defined in a schema instead of code. You can also use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Editor Plugin&lt;/a&gt; and change his configuration with those files.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Why did we choose Nx for AnyLogi
&lt;/h3&gt;

&lt;p&gt;Anylogi is a Logistics Management Platform connecting brands with WMSs, warehouses, and delivery companies worldwide. The Front end is built in Angular, with a NestJs application serving as a gateway to our Back-end. Since the application requires connection to multiple WMS with different guidelines and requirements, we decided to make the logic decoupled as much as possible. This would also come in handy since our app consists of various user types with different permissions and functionality.&lt;/p&gt;

&lt;p&gt;In previous projects I worked on, the basic approach to handle such cases was to create an Angular directive hiding or showing some UI elements, with conditions in code for calling or not some API. But such an approach makes scalability very difficult. The more User Roles added, the more conditions and logic were added to the FE, making it hard to maintain and test the multiple cases. Another issue we faced was when creating customized user roles functionality and experiences. In some cases, we wanted error messages for the admins to be more detailed than for users. In other, we would show advanced steps or fields for admins while simplifying the same process to users. All those changes would add additional conditions and fragment our application in parts that were not working together in harmony.&lt;/p&gt;

&lt;p&gt;With Anylogi, we decided to follow the Monorepo approach. Instead of having a single project with a hard-to-grasp logic and conditions all over the place, or multiple repositories that would need to work as one, we built a single Monorepo with Nx to handle our various projects and libraries. It makes things quicker and easier when sharing common logic, modules, and features across our workspace while maintaining the ability to easily customize the experience of a specific user type. &lt;/p&gt;

&lt;p&gt;We created three projects based on our user roles requirements and desired experience. We separated some common components used in those three projects (like the headers, logins pages, etc.) in UI libraries used across all projects. Finally, We separated our feature logic into various feature libraries, that way, it would be simple to add or remove functionality when needed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-contents.anymindgroup.com%2Fcorporate%2Fwp-uploads%2F2021%2F09%2F29174507%2Fanylogi_dep_graph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-contents.anymindgroup.com%2Fcorporate%2Fwp-uploads%2F2021%2F09%2F29174507%2Fanylogi_dep_graph.png" title="Anylogi dependency graph" alt="Anylogi dependency graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to Nx cached operations, we can modify a single Front-end app and deploy it independently of the others, or modify a library, rebuild the dependencies and deploy only that library-affected apps. &lt;/p&gt;

&lt;p&gt;One thing we missed and might add later is the addition of our NestJS gateway to this mono repository. Right now, our Back-end Gateway exists on a different repository, which creates some code duplication, but it would work all the same, if not better, if we added it in our Monorepo.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Create A Simple Nx Monorepo
&lt;/h3&gt;

&lt;p&gt;In this last part, we will create a simple Nx Monorepo with a project depending on a library. We are going to use angular, but you are free to set up React or View. &lt;br&gt;
Be sure to replace by what you want the content between bracket &lt;code&gt;{ }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start by creating our workspace.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994083800%2FyahEIECqQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994083800%2FyahEIECqQ.png" alt="Workspace initialization options"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will have to choose the workspace's name, what to create in it, and additional options based on what you selected. I chose angular for this example, but you can use whatever you want or add new projects and libraries later. You will also be prompted to use Nx Cloud, I will not go over it in this blog, but you can find more information on the Nx website &lt;a href="https://nx.app/" rel="noopener noreferrer"&gt;Nx Cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can test the project by navigating in the workspace and launch the project (those names are the ones you set previously) :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ./{workspaceName}/
npx nx serve {applicationName}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;you should see on &lt;code&gt;http://localhost:4200/&lt;/code&gt; the default Nx start page: &lt;br&gt;
    &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994103868%2FSlM-DEaxo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994103868%2FSlM-DEaxo.png" alt="Landing Page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s now add a library :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx g @nrwl/angular:lib {libraryName}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will generate a new folder under &lt;code&gt;libs&lt;/code&gt; named like your library and will contain the code defining your library. By default, this will result in an angular module named like the library. But Nx will also add additional configuration in your workspace, the most crucial part being the following.&lt;/p&gt;

&lt;p&gt;If you go to the &lt;code&gt;tsconfig.base.ts&lt;/code&gt; at the root of the project, you will see a new line added that should look like (with the name you selected) :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"paths": {
    "@{applicationName}/{libraryName}": ["libs/{libraryName}/src/index.ts"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This absolute import path points to your library definition. Anything exported in this file will be sharable across your workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994121396%2FC7XjWj-4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994121396%2FC7XjWj-4v.png" alt="Library export file"&gt;&lt;/a&gt;&lt;br&gt;
For Nx to work correctly and your project to be clean, &lt;strong&gt;ANYTHING&lt;/strong&gt; that you want to export from the library should be present in this file. Additionally, &lt;strong&gt;EVERY&lt;/strong&gt; project that uses this library must &lt;strong&gt;ONLY&lt;/strong&gt; import and use what is defined in this file.&lt;/p&gt;

&lt;p&gt;Let's add a component to this library. We will use the Nx CLI to generate the boilerplate the same way Angular CLI does it. I usually use &lt;a href="https://bradfrost.com/blog/post/atomic-web-design/" rel="noopener noreferrer"&gt;Atomic Design&lt;/a&gt; to organize my components, but for the sake of simplicity, let’s add it at the root of the library.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ./libs/{libraryName}/src/lib/
npx nx g @nrwl/angular:component {componentName}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Voila! We created a component the same way we usually do, and it is already declared in the library module. Let's add some code to this component at the top of the Nx demo page. I will create a simple text header.&lt;/p&gt;

&lt;p&gt;in the &lt;code&gt;.html&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="topnav"&amp;gt;
   Library Header
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;in the &lt;code&gt;.css&lt;/code&gt; (or whatever per-processor you chose)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.topnav {
   background-color: rgb(94, 94, 255);
   overflow: hidden;
   width: 100%;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Double-check if the component is correctly added to the library module using the name you have previously chosen for your library and component. In my case, it looks like this : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`@NgModule({
    imports: [CommonModule],
    exports: [HeaderComponent],
    declarations: [HeaderComponent],
})
export  class  SharedUiModule {}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;index.ts&lt;br&gt;
&lt;code&gt;export  *  from  './lib/shared-ui.module';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Check also that the module is exported in the library entry point (index.ts). If yes, let's import our library into our main project. &lt;/p&gt;

&lt;p&gt;Navigate to the &lt;code&gt;AppModule&lt;/code&gt; of our application and import our library module by using the &lt;strong&gt;ABSOLUTE PATH&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994141388%2F_9UoKxLNg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994141388%2F_9UoKxLNg.png" alt="Module import"&gt;&lt;/a&gt;&lt;br&gt;
Now add our component in our project &lt;code&gt;app.component.html&lt;/code&gt;, and you should see it appear :&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994155903%2FEE-Wqnhhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994155903%2FEE-Wqnhhf.png" alt="Custom Landing Page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now also use &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx dep-graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;to generate the simple dependency graph of our project :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994174520%2FahZGXQrbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1632994174520%2FahZGXQrbu.png" alt="Demo dependency graph"&gt;&lt;/a&gt;&lt;br&gt;
You can find this very simple Monorepo here &lt;a href="https://github.com/Crocsx/blog-posts/introduction-to-nx-and-monorepo/exemple" rel="noopener noreferrer"&gt;https://github.com/Crocsx&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Conclusion
&lt;/h3&gt;

&lt;p&gt;There is a lot more you can set up on NX to make your project easier to manage, and we only scratched the surface. I hope this short blog post gives you enough information to understand the basics and the possible applications of such a tool for your future project. I hope to go more in detail in a future blog post and showcase much more functionality. Until then, have a great one!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nx</category>
      <category>tutorial</category>
      <category>organize</category>
    </item>
    <item>
      <title>Remove automatic zoomIn of inputs on IOS</title>
      <dc:creator>Federico Giacomini</dc:creator>
      <pubDate>Tue, 11 May 2021 04:28:55 +0000</pubDate>
      <link>https://dev.to/crocsx/remove-automatic-zoom-in-of-inputs-on-ios-1cn0</link>
      <guid>https://dev.to/crocsx/remove-automatic-zoom-in-of-inputs-on-ios-1cn0</guid>
      <description>&lt;p&gt;Hello, First post here.&lt;/p&gt;

&lt;p&gt;I decided to use this platform to write reminders for myself, and quick tips to help everyone during daily development.&lt;/p&gt;

&lt;p&gt;Today I had to face a problem on IOS where Safari decides to auto zoom on inputs when user click on them.&lt;/p&gt;

&lt;p&gt;This happens when the font-size is considered too small by Apple (because yes, they decide what they want for you always right ?) which is apparently 16px.&lt;/p&gt;

&lt;p&gt;Anyway, after searching over the internet for quite some times, and finding posts ranging from 2014 to today, I ended up with this simple solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8" /&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /&amp;gt;
    &amp;lt;script&amp;gt;
      const el = document.querySelector('meta[name=viewport]');
      const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) &amp;amp;&amp;amp; !('MSStream' in window);
      if (isIOS) {
        const metaViewport = document.querySelector('meta[name=viewport]');
        metaViewport.content =
          'width=device-width, initial-scale=1, shrink-to-fit=no, minimum-scale=1, maximum-scale=1';
      }
    &amp;lt;/script&amp;gt;
  &amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is to add &lt;code&gt;minimum-scale=1, maximum-scale=1&lt;/code&gt; &lt;strong&gt;ONLY&lt;/strong&gt; for IOS. This will allow your users on desktop/android/iOs to correctly use the app without affecting their ability to manually zoom. And remove only the automatic zoom behavior of Apple devices.&lt;/p&gt;

&lt;p&gt;Hope this helps&lt;/p&gt;

&lt;p&gt;You can find a lot of ideas on this SO post (included the answer I followed)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/2989263/disable-auto-zoom-in-input-text-tag-safari-on-iphone"&gt;https://stackoverflow.com/questions/2989263/disable-auto-zoom-in-input-text-tag-safari-on-iphone&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
