<?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: Daniil Rabizo</title>
    <description>The latest articles on DEV Community by Daniil Rabizo (@dnlrbz).</description>
    <link>https://dev.to/dnlrbz</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%2F1009070%2Fae5dce15-7399-423a-96ab-7f6273701305.jpeg</url>
      <title>DEV Community: Daniil Rabizo</title>
      <link>https://dev.to/dnlrbz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dnlrbz"/>
    <language>en</language>
    <item>
      <title>NX Angular monorepo and shared NgRx store</title>
      <dc:creator>Daniil Rabizo</dc:creator>
      <pubDate>Mon, 16 Jan 2023 11:12:15 +0000</pubDate>
      <link>https://dev.to/dnlrbz/nx-angular-monorepo-and-shared-ngrx-store-h83</link>
      <guid>https://dev.to/dnlrbz/nx-angular-monorepo-and-shared-ngrx-store-h83</guid>
      <description>&lt;h2&gt;
  
  
  THE ARCHITECTURAL GUIDE FOR SHARED STORE IN ANGULAR NX MONOREPO
&lt;/h2&gt;

&lt;p&gt;In a project setting, where you have multiple Angular apps in a monorepo and some shared NgRx state, which these apps use, you would definitely want to &lt;strong&gt;avoid duplicating the store code&lt;/strong&gt; in each app. For that you should create an NX library and &lt;strong&gt;extract the reusable part of the store&lt;/strong&gt; there.&lt;/p&gt;

&lt;p&gt;In this guide, I will demonstrate an example of 2 different apps: “Product Shop” and “Product Rent Agency”, which &lt;em&gt;share the same Products state&lt;/em&gt;, therefore use the shared product store library and &lt;strong&gt;extend it with their own actions, effects, reducers and selectors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The “Product Shop” and “Product Rent Agency” &lt;strong&gt;both have to fetch all products&lt;/strong&gt;, so we need a FETCH &lt;strong&gt;action, effect and reducer, and this is the reusable code, we want to extract to the shared store library.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, “Product Shop” can also SELL products, and “Product Rent Agency” can RENT products, which are completely different actions and require their own NgRx logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  NX store library architecture
&lt;/h2&gt;

&lt;p&gt;We create an NX library for the reusable parts of the store and create a store in each app as well. Each concrete store is going to extend a shared store library.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The shared library should not know any implementation details about concrete apps using it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For that we are going to use &lt;strong&gt;Injection Token&lt;/strong&gt; for an API URL, and &lt;strong&gt;import shared store&lt;/strong&gt; parts in the concrete applications, but first let’s start with creating an NX library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a shared store library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx g @nrwl/angular:ngrx --module=libs/shared-store/src/lib/shared-store.module.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Add a store to each concrete app as well
&lt;/h3&gt;

&lt;p&gt;Generate NgRx store in the NX Angular application, for example for our product-shop:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx g @nrwl/angular:ngrx product-shop --root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a module for each app and register Effects and Store there, as we did in Product Shop application:&lt;/p&gt;

&lt;p&gt;registering store for Product Shop app:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;registering store for Product Rent Agency app:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Note that each app should use the same &lt;code&gt;PRODUCTS_FEATURE_KEY&lt;/code&gt;, so that we can &lt;strong&gt;register Store with this key, and shared store actions are triggered from concrete applications&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an API token
&lt;/h3&gt;

&lt;p&gt;This is important to isolate shared library from knowing the details about outside applications.&lt;/p&gt;

&lt;p&gt;It still has to perform API calls with different URLs, but not know the details about Product Shop or Product Rent Agency applications. So we have to &lt;strong&gt;provide an API TOKEN in concrete applications with its own API URL&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * necessary for generic effects, calling different API endpoints for each app
 */
export const API_TOKEN = new InjectionToken('apiToken');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;AppModule&lt;/code&gt; of Product Rent Agency:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;providers: [
    { provide: API_TOKEN, useValue: '/product-rent-agency/api' }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;AppModule&lt;/code&gt; of Product Shop:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;providers: [
    { provide: API_TOKEN, useValue: '/product-shop/api' }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Actions
&lt;/h3&gt;

&lt;p&gt;Each application has to fetch products, so we create &lt;strong&gt;reusable product actions in the NX library&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;actions for fetching products:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;And “Product Shop” app has its own concrete actions to SELL products:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And “Product Rent Agency” can RENT products:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Effects
&lt;/h3&gt;

&lt;p&gt;We are using &lt;code&gt;API_TOKEN&lt;/code&gt; here so that each application can call its own different API URL, even while using shared &lt;code&gt;ProductsEffects&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Calling API to fetch products with an API_TOKEN:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can define any logic in concrete Effects we want, for example in Product Rent Agency we Rent the product and call the respective API for that:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In Product Shop we also might want to have some effects, for example to sell the product with an API call:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Reducers
&lt;/h3&gt;

&lt;p&gt;Make sure to &lt;strong&gt;export shared reducers as an array&lt;/strong&gt;, in order to import and reuse them later in concrete apps. In this example we export &lt;code&gt;productReducers&lt;/code&gt;, which we are going to &lt;strong&gt;import and use with help of spread operator&lt;/strong&gt; &lt;code&gt;...productReducers&lt;/code&gt; in concrete reducers in Product Shop and Product Rent Agency.&lt;/p&gt;

&lt;p&gt;Shared Product Reducers:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Reducers of Product Shop for updating its state when selling products, and imported productReducers with spread operator:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Reducers of Product Rent Agency, and imported productReducers with spread operator:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Selectors
&lt;/h3&gt;

&lt;p&gt;There are reusable selectors which select the shared part of the state, as well as concrete selectors for concrete state parts. Both shared and concrete &lt;strong&gt;use the same&lt;/strong&gt; &lt;code&gt;PRODUCTS_FEATURE_KEY&lt;/code&gt; &lt;strong&gt;to access the state&lt;/strong&gt;. This feature key is the only thing that is binding these selectors, so they are loosely coupled.&lt;/p&gt;

&lt;p&gt;For example shared state has the &lt;code&gt;isLoading&lt;/code&gt; flag, which we want to use in both apps, so let’s define a shared selector for that:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And some selectors to select the concrete state of Product Rent Agency, let’s assume we want to select all Products and the number of rented items, which is part only of Product Rent Agency:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And for Product Shop we want to select revenue, which exists only in Product Shop:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;With this implementation we have reduced code duplication for the same NgRx logic, that both apps use, by extracting it into the NX library.&lt;/p&gt;

&lt;p&gt;See the whole implementation of an NX shared store library and two different apps inside the NX monorepo in my GitHub:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/dnlrbz" rel="noopener noreferrer"&gt;
        dnlrbz
      &lt;/a&gt; / &lt;a href="https://github.com/dnlrbz/ngrx-in-monorepo" rel="noopener noreferrer"&gt;
        ngrx-in-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Using shared NgRx store in NX Angular monorepo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Ngrx In Monorepo&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Shared store library and 2 different apps using it&lt;/p&gt;
&lt;p&gt;This project was generated with &lt;a href="https://github.com/angular/angular-cli" rel="noopener noreferrer"&gt;Angular CLI&lt;/a&gt; version 14.2.3.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://medium.com/@danilrabizo/nx-angular-monorepo-and-shared-ngrx-store-f34bb3bb2bb5" rel="nofollow noopener noreferrer"&gt;Documentation article&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dnlrbz/ngrx-in-monorepo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>discuss</category>
      <category>welcome</category>
      <category>devops</category>
      <category>saas</category>
    </item>
    <item>
      <title>Building a reusable and configurable table with Angular Material 15</title>
      <dc:creator>Daniil Rabizo</dc:creator>
      <pubDate>Mon, 16 Jan 2023 09:51:18 +0000</pubDate>
      <link>https://dev.to/dnlrbz/building-a-reusable-and-configurable-table-with-angular-material-15-2i1g</link>
      <guid>https://dev.to/dnlrbz/building-a-reusable-and-configurable-table-with-angular-material-15-2i1g</guid>
      <description>&lt;p&gt;The &lt;code&gt;mat-table&lt;/code&gt; in Angular Material provides a data-table that can be used to display rows of data, but it is not reusable and leads to a lot of code duplication.&lt;/p&gt;

&lt;p&gt;Therefore there is a possibility to build your own &lt;strong&gt;reusable&lt;/strong&gt; generic table on its basis, with optionally &lt;strong&gt;configurable pagination, filtering, sorting, columns and row actions&lt;/strong&gt;, just using Angular and Material Design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table component
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Column interface
&lt;/h3&gt;

&lt;p&gt;First of all, we have to define the column interface, in order to pass the column information to the table from a parent component:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Table
&lt;/h3&gt;

&lt;p&gt;Secondly, we create our reusable table component with &lt;code&gt;ng generate component table&lt;/code&gt; command, and define &lt;em&gt;configurable input and output paramaters&lt;/em&gt; in the .ts file, which are being passed from parent component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Input from the parent component:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;isPageable&lt;/code&gt;: should the table have pagination?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isSortable&lt;/code&gt;: should the table have sorting?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isFilterable&lt;/code&gt;: should there be a filter, operating on the whole table?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tableColumns&lt;/code&gt;: columns of type interface TableColumn👆🏻 with parameters (name, dataKey, position, isSortable)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rowActionIcon&lt;/code&gt;: name of the mat-icon, that is going to be embedded in each row.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;paginationSizes&lt;/code&gt;: options for rows number on a page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;defaultPageSize&lt;/code&gt;: default number of rows on a page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tableData&lt;/code&gt;: the actual data, which must have a setter, to dynamically get changes of the from parent component (e.g. after sorting it in parent). If we want to apply pipes or services on this data, we should do it in the parent component beforehand, and pass the “ready to display” data in the table.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Output events to the parent component:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sort&lt;/code&gt;: Outputs the key to sort with, and the direction(ascending, descending). The sorting logic must be implemented in the parent component, in order to keep the table abstract and simple. Moreover, sorting of different datatypes, e.g. Date and string has different logic, and it is impossible to foresee all sorting strategies in the table.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rowAction&lt;/code&gt;: Outputs the whole row, when a user clicks on the action-icon in the given row.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Table template
&lt;/h3&gt;

&lt;p&gt;Thirdly, we define a template for the table component, and make almost everything optional with &lt;code&gt;*ngIf&lt;/code&gt; directive, for instance: filter, row-action, sorting and pagination:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;We have created &lt;code&gt;customers-table&lt;/code&gt; and &lt;code&gt;orders-table&lt;/code&gt; components, which use our generic table component and pass data to it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;customers-table&lt;/code&gt; component only uses basic table features, therefore it only passes the data array and columns definition to the table.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;orders-table&lt;/code&gt; uses all features of table and explicitly passes all optional parameters, to turn on the pagination, filtering and sorting.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Complete code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/dnlrbz"&gt;
        dnlrbz
      &lt;/a&gt; / &lt;a href="https://github.com/dnlrbz/material-reusable-table"&gt;
        material-reusable-table
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Reusable Angular Material table&lt;/h1&gt;
&lt;p&gt;Documentation: &lt;a href="https://medium.com/@danilrabizo/reusable-angular-material-table-ac0b02162293" rel="nofollow"&gt;https://medium.com/@danilrabizo/reusable-angular-material-table-ac0b02162293&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Project for configurable and reusable angular material table
&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/34266035/131548037-ad2156b8-b062-4695-8670-8c8ec37cb127.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_RaFgg3H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/34266035/131548037-ad2156b8-b062-4695-8670-8c8ec37cb127.gif" alt="1_rIwXvPHmmvPbd2TagMvNRw"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Development server&lt;/h2&gt;
&lt;p&gt;Run &lt;code&gt;ng serve&lt;/code&gt; for a dev server. Navigate to &lt;code&gt;http://localhost:4200/&lt;/code&gt;. The app will automatically reload if you change any of the source files.&lt;/p&gt;
&lt;h2&gt;
Build&lt;/h2&gt;
&lt;p&gt;Run &lt;code&gt;ng build&lt;/code&gt; to build the project. The build artifacts will be stored in the &lt;code&gt;dist/&lt;/code&gt; directory. Use the &lt;code&gt;--prod&lt;/code&gt; flag for a production build.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dnlrbz/material-reusable-table"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>angular</category>
      <category>material</category>
      <category>table</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
