<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Katerina Gable | Kate Gable</title>
	<atom:link href="https://www.katesky.com/author/kateskytech/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.katesky.com</link>
	<description>sharing knowledge, encouraging to learn, promoting passion for coding, supporting mothers who code</description>
	<lastBuildDate>Fri, 27 Dec 2024 20:39:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
<site xmlns="com-wordpress:feed-additions:1">193364748</site>	<item>
		<title>Balancing Motherhood</title>
		<link>https://www.katesky.com/2024/12/27/balancing-motherhood/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=balancing-motherhood</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Fri, 27 Dec 2024 20:39:24 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=298</guid>

					<description><![CDATA[<p>Balancing Motherhood, Career, and Self: A Therapist’s Mission to Empower Women Since becoming a therapist, I’ve realized the immense power of combining my newfound love for therapy with my extensive experience as a software engineer. My mission is to help women who <br /><a href="https://www.katesky.com/2024/12/27/balancing-motherhood/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2024/12/27/balancing-motherhood/">Balancing Motherhood</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<p><strong>Balancing Motherhood, Career, and Self: A Therapist’s Mission to Empower Women</strong></p>



<p>Since becoming a therapist, I’ve realized the immense power of combining my newfound love for therapy with my extensive experience as a software engineer. My mission is to help women who live in constant doubt—doubt about whether they can be loving mothers, successful professionals, and fulfilled individuals all at once. Through mentoring and coaching, I guide women toward a life where they can thrive in all their roles without compromising their identity or happiness.</p>



<h3 class="wp-block-heading">Why Women Struggle with Balance</h3>



<p>As a therapist and a mother of five children, I’ve lived the challenges many women face daily. The pressure to excel in every role can leave you feeling like you’re constantly falling short. For many, this leads to doubt, guilt, and even burnout.</p>



<ul class="wp-block-list">
<li><strong>“Am I spending enough time with my children?”</strong></li>



<li><strong>“Is my career taking too much away from my family?”</strong></li>



<li><strong>“Will I ever feel like I’m enough in any area of my life?”</strong></li>
</ul>



<p>These are the questions I hear from women every day—and ones I’ve asked myself in my journey.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h3 class="wp-block-heading">Combining Therapy and Technology: A Unique Approach</h3>



<p>With over 25 years as a software engineer, I’ve honed problem-solving, analytical thinking, and systems design—skills I now apply in my work as a therapist and coach. Just as technology solutions require careful planning and optimization, so do our lives.</p>



<p><strong>Here’s how I bring this unique blend of expertise to my work with women:</strong></p>



<ol start="1" class="wp-block-list">
<li><strong>Identifying Patterns</strong><br>Using a systematic approach, I help women uncover the beliefs and habits that keep them stuck in cycles of doubt and stress.</li>



<li><strong>Breaking Down Goals</strong><br>Just as I would design software solutions step by step, I guide my clients in breaking down their ambitions into achievable, actionable goals.</li>



<li><strong>Building Confidence</strong><br>Through mentoring, I help women see their worth beyond the roles they play, empowering them to embrace both their professional aspirations and their personal lives.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h3 class="wp-block-heading">Mentoring and Coaching: My Mission to Empower Women</h3>



<p>My work goes beyond therapy. I provide mentoring and coaching to women who want to reclaim their sense of self and live a life of purpose and fulfillment. My mission is to create a community of women who support each other in redefining what success looks like.</p>



<ul class="wp-block-list">
<li><strong>For the mom who feels torn between family and career,</strong> I offer strategies to create harmony in both.</li>



<li><strong>For the professional struggling with imposter syndrome,</strong> I help build confidence and clarity.</li>



<li><strong>For the woman who feels she’s lost herself,</strong> I provide the tools to reconnect with her passions and dreams.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h3 class="wp-block-heading">A Life Where You Can Thrive</h3>



<p>The idea that you must choose between being a present mother and a successful professional is outdated. You can have both, but it requires intention, self-compassion, and a willingness to redefine balance.</p>



<p>Through therapy, mentoring, and coaching, I help women step out of doubt and into confidence. Whether it’s through one-on-one sessions or group workshops, I guide women toward living authentically and embracing their full potential.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h3 class="wp-block-heading">Are You Ready to Reclaim Your Life?</h3>



<p>If you’re struggling to find harmony between motherhood, career, and self, I’m here to help. Together, we’ll explore your unique challenges and create a personalized path to a life where you feel fulfilled, confident, and whole.</p>



<p>You don’t have to navigate this journey alone. Let’s work together to turn your doubt into strength and your dreams into reality.</p>



<p><strong>Because you deserve to thrive—not just as a mother or a professional, but as </strong><em><strong>you</strong></em><strong>.</strong></p>



<p></p>



<p></p>
</body>The post <a href="https://www.katesky.com/2024/12/27/balancing-motherhood/">Balancing Motherhood</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">298</post-id>	</item>
		<item>
		<title>Harnessing Angular 19’s Resource API: A Declarative Approach to Data Management</title>
		<link>https://www.katesky.com/2024/12/07/harnessing-angular-19s-resource-api-a-declarative-approach-to-data-management/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=harnessing-angular-19s-resource-api-a-declarative-approach-to-data-management</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Sat, 07 Dec 2024 06:13:07 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=290</guid>

					<description><![CDATA[<p>Introducing resource Angular 19 brings an exciting addition to its toolkit: the Resource API. This API is designed to simplify asynchronous data fetching and state management, making it more declarative and easier to integrate into Angular’s reactive ecosystem. In this blog, we’ll <br /><a href="https://www.katesky.com/2024/12/07/harnessing-angular-19s-resource-api-a-declarative-approach-to-data-management/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2024/12/07/harnessing-angular-19s-resource-api-a-declarative-approach-to-data-management/">Harnessing Angular 19’s Resource API: A Declarative Approach to Data Management</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<p><strong>Introducing resource</strong></p>



<p>Angular 19 brings an exciting addition to its toolkit: the <strong>Resource API</strong>. This API is designed to simplify asynchronous data fetching and state management, making it more declarative and easier to integrate into Angular’s reactive ecosystem.</p>



<p>In this blog, we’ll explore:</p>



<ul class="wp-block-list">
<li>The benefits of the Resource API</li>



<li>How it compares to traditional <code>HttpClient</code> implementations</li>



<li>A complete example using <strong>products</strong> data, showcasing filtering by category with <code>linkedSignal</code></li>
</ul>



<h2 class="wp-block-heading"><strong>What is the Resource API?</strong></h2>



<p>The Resource API leverages Angular’s reactivity model to provide:</p>



<ul class="wp-block-list">
<li><strong>Declarative data fetching</strong>: Define and manage resources with minimal boilerplate.</li>



<li><strong>Automatic state management</strong>: Built-in handling of loading, errors, and data updates.</li>



<li><strong>Reactive signals</strong>: Seamless synchronization with Angular’s <code>signal</code> and <code>linkedSignal</code>.</li>
</ul>



<h2 class="wp-block-heading"><strong>How Does It Compare to the Traditional Approach?</strong></h2>



<h3 class="wp-block-heading"><strong>The Old Way</strong></h3>



<p>In pre-Angular 19 applications, data was often fetched using <code>HttpClient</code> within services, requiring manual state management. Here’s an example:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
// Old service implementation
getProducts(): Observable&lt;Product[]&gt; {
  return this.http.get&lt;Product[]&gt;('https://api.example.com/products');
}

// Old component implementation
this.productService.getProducts().subscribe({
  next: (data) =&gt; { this.products = data; this.isLoading = false; },
  error: (err) =&gt; { this.error = err.message; this.isLoading = false; }
});

</pre></div>


<h4 class="wp-block-heading"><strong>Drawbacks</strong></h4>



<ol class="wp-block-list">
<li><strong>Manual State Management</strong>: Developers had to handle loading, errors, and data updates manually in every component.</li>



<li><strong>Boilerplate Code</strong>: Each service and component required repetitive code for fetching data and managing states.</li>



<li><strong>Complexity with Derived States</strong>: Filtering and transforming data often required separate streams or additional logic.</li>



<li><strong>Inconsistent Practices</strong>: Different developers might manage states differently, leading to inconsistent patterns across the codebase.</li>
</ol>



<h3 class="wp-block-heading"><strong>The New Way with Resource API</strong></h3>



<p>With the Resource API, the repetitive parts of state management are handled automatically:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
products = resource({
  loader: async () =&gt; {
    const response = await fetch('https://api.example.com/products');
    if (!response.ok) {
      throw new Error('Failed to fetch products');
    }
    return response.json();
  },
});

</pre></div>


<h4 class="wp-block-heading"><strong>Why It’s Better Long Term</strong></h4>



<ol class="wp-block-list">
<li><strong>Declarative Syntax</strong>: The Resource API makes data fetching and state management part of the Angular reactivity model. Developers define what data they need and how it should react to changes, and Angular handles the rest.</li>



<li><strong>Built-In State Management</strong>: Automatic handling of loading, error, and data states simplifies component logic.</li>



<li><strong>Derived State with Signals</strong>: The seamless integration with <code>linkedSignal</code> allows for effortless creation of derived states (e.g., filtering products by category).</li>



<li><strong>Reduced Boilerplate</strong>: Say goodbye to repetitive loading/error handling code in every component.</li>



<li><strong>Consistency</strong>: Provides a standard way to manage data across the application, making it easier to onboard new developers or refactor code.</li>



<li><strong>Future-Ready</strong>: The Resource API aligns with Angular’s long-term strategy of reactive, signal-based development, ensuring compatibility and smoother upgrades in the future.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h2 class="wp-block-heading"><strong>Building a Product List with the Resource API</strong></h2>



<p>Let’s dive into a practical example: fetching and displaying products with filtering by category.</p>



<h3 class="wp-block-heading"><strong>Service Implementation</strong></h3>



<p>Here’s how to set up the Resource API in your <code>ProductService</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
import { Injectable, signal, resource } from '@angular/core';
import { Product, Response } from './Product';

@Injectable({
  providedIn: 'root',
})
export class ProductService {
  private apiUrl = 'https://dummyjson.com/products';

  // Signal to trigger the resource loader
  private trigger = signal&amp;lt;void&gt;(undefined);

  // Resource to fetch products
  products = resource({
    request: () =&gt; this.trigger,
    loader: async () =&gt; {
      const response = await fetch(this.apiUrl);
      if (!response.ok) {
        throw new Error('Failed to fetch products');
      }
      const data = response.json() as Promise&amp;lt;Response&gt;;
      return (await data).products;
    },
  });

  // Method to reload products
  reload() {
    this.trigger.set(undefined);
  }
}

</pre></div>


<h3 class="wp-block-heading"><strong>Component with Linked Signals</strong></h3>



<p>In the component, <code>linkedSignal</code> is used to manage derived states, like the list of categories and filtered products.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
import { Component, effect, linkedSignal, signal } from '@angular/core';
import { ProductService } from '../product.service';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css'],
})
export class ProductListComponent {
  productsResource = this.productService.products;
  selectedCategory = signal&lt;string&gt;('all');

  categories = linkedSignal(() =&gt; {
    if (!this.productsResource.value()) return [];
    return Array.from(
      new Set(
        this.productsResource.value()?.map((product) =&gt; product.category)
      )
    );
  });

  filteredProducts = linkedSignal(() =&gt; {
    const category = this.selectedCategory();
    if (category === 'all') return this.productsResource.value();
    return this.productsResource.value()?.filter(
      (product) =&gt; product.category === category
    );
  });

  constructor(private productService: ProductService) {}

  selectCategory(e: any) {
    this.selectedCategory.set(e.target.value);
  }

  reload() {
    this.selectedCategory.set('all');
    this.productService.reload();
  }
}

</pre></div>


<h3 class="wp-block-heading"><strong>The Benefits in Action</strong></h3>



<ol class="wp-block-list">
<li><strong>Automatic State Management</strong>: Loading, data, and error states are built into the Resource API.</li>



<li><strong>Simplified UI Logic</strong>: The use of <code>linkedSignal</code> ensures that the UI automatically updates when data or user selections change.</li>



<li><strong>Consistency Across Features</strong>: The same declarative pattern can be used for other data resources, ensuring uniformity across the app.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>Angular 19’s Resource API is a significant step forward for Angular developers. By combining declarative data fetching with reactive signals, it provides:</p>



<ul class="wp-block-list">
<li>Cleaner code</li>



<li>Enhanced maintainability</li>



<li>A more consistent developer experience</li>
</ul>



<p>When compared to the traditional approach, the Resource API not only reduces boilerplate but also aligns with Angular’s vision for reactive, signal-driven development, ensuring its relevance for years to come.</p>



<p>If you’re still using the old way, now is the time to embrace the future with Angular 19. What do you think about the Resource API? Let’s discuss in the comments below!</p>



<p>Checkout complete code example here:  <a href="https://github.com/kategable/stackblitz-starters-linkedSignal" target="_blank" rel="noopener" title="">https://github.com/kategable/stackblitz-starters-linkedSignal</a></p>



<p>and StackBlitz: <a href="https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal" target="_blank" rel="noopener" title="">https://stackblitz.com/~/</a><a href="https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal?file=src/app/demo-r/product-list.component.ts" target="_blank" rel="noopener" title="">github.com/kategable/stackblitz-starters-linkedSignal</a></p>



<p>get more Angularv19 here <a href="https://blog.angular.dev/meet-angular-v19-7b29dfd05b84" target="_blank" rel="noopener" title="">https://blog.angular.dev/meet-angular-v19-7b29dfd05b84</a></p>



<p></p>
</body>The post <a href="https://www.katesky.com/2024/12/07/harnessing-angular-19s-resource-api-a-declarative-approach-to-data-management/">Harnessing Angular 19’s Resource API: A Declarative Approach to Data Management</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">290</post-id>	</item>
		<item>
		<title>Dynamic Filtering with Angular&#8217;s linkedSignal v19</title>
		<link>https://www.katesky.com/2024/12/05/dynamic-filtering-with-angulars-linkedsignal-v19/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamic-filtering-with-angulars-linkedsignal-v19</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Thu, 05 Dec 2024 19:02:33 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=283</guid>

					<description><![CDATA[<p>Exploring Angular’s linkedSignal: Enhancing Signal Reusability In Angular applications, managing state and reactivity often involves tools like BehaviorSubject from RxJS. With the advent of signals, particularly linkedSignal, Angular provides a declarative and more Angular-native approach to handling dynamic state transformations. Let’s build <br /><a href="https://www.katesky.com/2024/12/05/dynamic-filtering-with-angulars-linkedsignal-v19/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2024/12/05/dynamic-filtering-with-angulars-linkedsignal-v19/">Dynamic Filtering with Angular’s linkedSignal v19</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<p><strong>Exploring Angular’s <code>linkedSignal</code>: Enhancing Signal Reusability</strong></p>



<p>In Angular applications, managing state and reactivity often involves tools like <code>BehaviorSubject</code> from RxJS. With the advent of signals, particularly <code>linkedSignal</code>, Angular provides a declarative and more Angular-native approach to handling dynamic state transformations.</p>



<p>Let’s build a product filtering example to see how <code>linkedSignal</code> can simplify state management and potentially replace <code>BehaviorSubject</code>.</p>



<p>In this post, we’ll explore what <code>linkedSignal</code> is, its benefits, how it can replace <code>BehaviorSubject</code> in many use cases, and how you can implement it in your Angular applications.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h3 class="wp-block-heading"><strong>What is <code>linkedSignal</code>?</strong></h3>



<p>The <code>linkedSignal</code> function allows you to create a signal whose value is derived from other existing signals. Unlike computed signals that focus on recalculating values reactively, <code>linkedSignal</code> is more tailored for situations where the new signal’s lifecycle and reactivity are closely tied to another signal or context.</p>



<p>This makes <code>linkedSignal</code> a perfect choice when:</p>



<ul class="wp-block-list">
<li>You need to extend or transform the behavior of an existing signal.</li>



<li>You want to maintain a scoped reactive context within your application.</li>
</ul>



<h3 class="wp-block-heading"><strong>Why Replace <code>BehaviorSubject</code> with Signals?</strong></h3>



<p>Traditionally, Angular developers have relied on <code>BehaviorSubject</code> from RxJS for state management, such as holding and propagating reactive data. While powerful, <code>BehaviorSubject</code> has limitations that <code>linkedSignal</code> can address:</p>



<h4 class="wp-block-heading"><strong>1. Boilerplate Reduction</strong></h4>



<p>With <code>BehaviorSubject</code>, you often have to write additional boilerplate for initialization, subscriptions, and updates:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const subject = new BehaviorSubject&lt;number&gt;(0);
subject.next(5);
subject.subscribe(value =&gt; console.log(value));
</pre></div>


<p>In contrast, <code>linkedSignal</code> provides a more concise and declarative API:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const baseSignal = signal(0);
const linked = linkedSignal(() =&gt; baseSignal() * 2);
console.log(linked());

</pre></div>


<h4 class="wp-block-heading"><strong>2. Declarative State Management</strong></h4>



<p><code>linkedSignal</code> eliminates the need for manual subscription management, reducing the risk of memory leaks and simplifying code structure. It’s purely declarative, meaning dependencies and updates are handled automatically.</p>



<h4 class="wp-block-heading"><strong>3. Tight Integration with Angular</strong></h4>



<p>Unlike <code>BehaviorSubject</code>, which is an external library feature, <code>linkedSignal</code> is natively supported in Angular, ensuring seamless integration with other Angular features like templates and change detection.</p>



<h4 class="wp-block-heading"><strong>Scenario: Product Filtering</strong></h4>



<p>Imagine you have a list of products, and the user can filter them by category. Using <code>linkedSignal</code>, we can create a reactive filtered list that updates automatically whenever the category or product list changes.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
import { Component, signal, linkedSignal } from '@angular/core';

@Component({
  selector: 'app-product-filter',
  standalone: true,
  template: `
    &lt;h2&gt;Product Filter&lt;/h2&gt;
    &lt;div&gt;
      &lt;label&gt;Filter by Category:&lt;/label&gt;
      &lt;select [value]="selectedCategory()" (change)="selectCategory($event.target.value)"&gt;
        &lt;option value="all"&gt;All&lt;/option&gt;
        &lt;option *ngFor="let category of categories" [value]="category"&gt;
          {{ category }}
        &lt;/option&gt;
      &lt;/select&gt;
    &lt;/div&gt;

    &lt;div&gt;
      &lt;h3&gt;Products&lt;/h3&gt;
      &lt;ul&gt;
        &lt;li *ngFor="let product of filteredProducts()"&gt;
          {{ product.name }} - {{ product.category }}
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  `,
})
export class ProductFilterComponent {
  // Base signal for the list of products
  products = signal([
    { name: 'Laptop', category: 'Electronics' },
    { name: 'Headphones', category: 'Electronics' },
    { name: 'Sofa', category: 'Furniture' },
    { name: 'Table', category: 'Furniture' },
    { name: 'T-shirt', category: 'Clothing' },
  ]);

  // Signal for selected category
  selectedCategory = signal&lt;string&gt;('all');

  // Derived signal for filtering products based on the selected category
  filteredProducts = linkedSignal(() =&gt; {
    const category = this.selectedCategory();
    const allProducts = this.products();
    return category === 'all'
      ? allProducts
      : allProducts.filter(product =&gt; product.category === category);
  });

  // Generate a list of unique categories from the products
  get categories() {
    return Array.from(new Set(this.products().map(product =&gt; product.category)));
  }

  // Update the selected category
  selectCategory(category: string) {
    this.selectedCategory.set(category);
  }
}

</pre></div>


<hr class="wp-block-separator has-alpha-channel-opacity">



<h4 class="wp-block-heading"><strong>Component Code</strong></h4>



<hr class="wp-block-separator has-alpha-channel-opacity">



<p><a href="https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal?file=src/app/demo/demo.component.ts" target="_blank" rel="noopener" title="">https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal?file=src/app/demo/demo.component.ts</a></p>



<h4 class="wp-block-heading"><strong>How It Works</strong></h4>



<ol class="wp-block-list">
<li><strong>Signal Initialization</strong>:
<ul class="wp-block-list">
<li><code>products</code> contains a static list of products.</li>



<li><code>selectedCategory</code> holds the currently selected category.</li>
</ul>
</li>



<li><strong>Linked Signal</strong>:
<ul class="wp-block-list">
<li><code>filteredProducts</code> derives its value based on <code>products</code> and <code>selectedCategory</code>. It automatically recalculates when either signal changes.</li>
</ul>
</li>



<li><strong>Reactivity in Action</strong>:
<ul class="wp-block-list">
<li>When the user selects a category, the <code>filteredProducts</code> signal updates the displayed list of products dynamically.</li>
</ul>
</li>



<li>If we used <code><strong>BehaviorSubject</strong></code>:
<ul class="wp-block-list">
<li>Set up a subject, </li>



<li>add pipe for transformations, </li>



<li>add manual subscriptions or async pipe. </li>
</ul>
</li>



<li>With <code><strong>linkedSignal</strong></code>:
<ul class="wp-block-list">
<li>Avoid subscriptions entirely.</li>



<li>Use Angular’s built-in reactivity for value updates.</li>



<li>Keep the code cleaner and more concise.</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h4 class="wp-block-heading"><strong>Benefits of This Approach</strong></h4>



<ol class="wp-block-list">
<li><strong>Dynamic Updates</strong>: Any change in the product list or selected category immediately updates the filtered list.</li>



<li><strong>Code Clarity</strong>: The filtering logic is encapsulated within the <code>linkedSignal</code>, making it reusable and easier to test.</li>



<li><strong>Performance</strong>: Signals ensure efficient updates with minimal recalculations.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity">



<h3 class="wp-block-heading"><strong>When to Use <code>linkedSignal</code> Instead of <code>BehaviorSubject</code></strong></h3>



<p>Consider using <code>linkedSignal</code> when:</p>



<ul class="wp-block-list">
<li>You are managing state within Angular components or services.</li>



<li>You want a simpler, Angular-native alternative to RxJS subjects.</li>



<li>The logic requires automatic dependency tracking and updates.</li>
</ul>



<p>However, if you’re managing streams from external sources (e.g., WebSocket connections or complex asynchronous workflows), <code>BehaviorSubject</code> or other RxJS operators may still be more appropriate.</p>



<p></p>



<h3 class="wp-block-heading"><strong>Conclusion</strong></h3>



<p>Angular’s <code>linkedSignal</code> simplifies state management by allowing you to derive signals dynamically. This product filter example demonstrates how you can build responsive and dynamic applications with ease.</p>



<p>Give it a try in your next Angular project, and let me know if you want more examples or use cases!</p>



<p>Code link:</p>



<p>git clone <a href="https://github.com/kategable/stackblitz-starters-linkedSignal.git" target="_blank" rel="noopener" title="">https://github.com/kategable/stackblitz-starters-linkedSignal.git</a></p>



<p>stackblitz – <a href="https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal?file=src/app/demo/demo.component.ts" target="_blank" rel="noopener" title="">https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal?file=src/app/demo/demo.component.ts</a></p>



<p>get more Angularv19 here <a href="https://blog.angular.dev/meet-angular-v19-7b29dfd05b84" target="_blank" rel="noopener" title="">https://blog.angular.dev/meet-angular-v19-7b29dfd05b84</a></p>
</body>The post <a href="https://www.katesky.com/2024/12/05/dynamic-filtering-with-angulars-linkedsignal-v19/">Dynamic Filtering with Angular’s linkedSignal v19</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">283</post-id>	</item>
		<item>
		<title>Streamlining Application Development: Nx Monorepo’s Transformative Impact for Angular Developers.</title>
		<link>https://www.katesky.com/2023/10/11/streamlining-application-development-nx-monorepos-transformative-impact-for-angular-developers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=streamlining-application-development-nx-monorepos-transformative-impact-for-angular-developers</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Wed, 11 Oct 2023 16:57:58 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[Monorepo]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=277</guid>

					<description><![CDATA[<p>Streamlining Application Development: Nx Monorepo’s Transformative Impact for Angular Developers. In the fast-paced world of enterprise software development, I discovered Nx Monorepo as an Angular developer when I worked on a team converting AngularJs project to Angular, the latest version 14. That <br /><a href="https://www.katesky.com/2023/10/11/streamlining-application-development-nx-monorepos-transformative-impact-for-angular-developers/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2023/10/11/streamlining-application-development-nx-monorepos-transformative-impact-for-angular-developers/">Streamlining Application Development: Nx Monorepo’s Transformative Impact for Angular Developers.</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<p>Streamlining Application Development: Nx Monorepo’s Transformative Impact for Angular Developers.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<p>In the fast-paced world of enterprise software development, I discovered Nx Monorepo as an Angular developer when I worked on a team converting AngularJs project to Angular, the latest version 14. That was my first time working with nx on a production code, and I was so excited because I learned it in my free time and was eager to see all the benefits it would provide. This tool became a game-changer in streamlining the project, ensuring code quality, consistency, and developer satisfaction. It’s a transformative step that streamlines development, unites teams, and enhances efficiency. Do you want to be the hero on your team? Keep reading, and you will have all the tools to get your team to be on top of their development game.</p>



<p>In this article, we’ll explore how Nx Monorepo facilitates Angular development and provides practical steps for you to get started. But that’s not all. We’ll also delve into the challenges I faced when introducing Nx to my team, offering insights into how to move your team toward its adoption. Additionally, we’ll discuss the advantages of having this skill set, not just for your projects but also for your career growth. Join me on this journey to revolutionize your approach to building software solutions and empower your team for the future.</p>



<p>Let me begin by introducing myself. I’m Kate, and I’ve been involved in enterprise software development for the past 25 years. My time consulting at HeroDevs has been a highlight of my career, and I take pride in being a part of the team here. I specialize in web development using the Angular framework, although I am a full-stack developer.</p>



<p><strong>New Team</strong></p>



<p>When I joined my current project, it was already well into the advanced stages of development, with the beta version on the horizon. The team handed me a set of urgent user stories, and the deadline was rapidly approaching. In our current setup, each team operates within its own dedicated repository, with some teams already successfully utilizing Nx.</p>



<p>We’re currently immersed in a micro-frontend architecture project, creating a web component using the <a href="http://twitter.com/angular" rel="noreferrer noopener" target="_blank">@angular</a>-elements library. In the initial stages, we encountered a significant challenge: our unit-test coverage was alarmingly low. We found ourselves heavily dependent on the QA group, which isn’t an ideal situation. Our primary objective was to boost our unit test coverage to an ambitious 80%. However, given that a substantial portion of our code remained untested at a mere 30%, we had no choice but to allocate an entire sprint solely to the task of writing unit tests. Despite our dedicated efforts during that sprint, we still fell short of reaching the 80% target.</p>



<p><strong>Let us get started with Nx</strong></p>



<p>After our second production release, a significant challenge emerged: the integration of a substantial new feature. I was tasked with enhancing our approach to state management and component architecture. Simultaneously, we needed to plan a strategy for facilitating bi-directional communication in our micro-frontend setup.</p>



<p>One of my favorite features of Nx is the caching of tasks. Executing commands like build and test can be resource-intensive when working with a large codebase. However, Nx employs a computational cache, ensuring it doesn’t unnecessarily rebuild the same code. With a limited number of sprints available before our upcoming release, I began advocating for the adoption of Nx within our team.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<p><strong>Making the team believe it’s the right thing</strong></p>



<p>The initial step involved asking them if they were prepared to learn about the benefits of integrating Nx into our repository.<br>I created a task with the benefits of using nx. My primary goal is to ensure that other team members feel comfortable integrating this new and complex technology, thus minimizing potential adverse effects.</p>



<p>**1. Standardized Libraries and Applications:** <br> Using a mono repo approach, you can ensure that all repository applications use the <em>same versions</em> of libraries like Angular and, RxJS, NgRx. This helps maintain consistency and reduces the chances of compatibility issues arising when different projects use different library versions. With the new feature’s introduction, we plan to incorporate additional libraries. This strategic move allows us to run independent unit tests on the freshly added code, thus reaching the goal of 80% coverage, seamlessly integrating NgRx for state management, and introducing reusable code components essential for integration purposes. Moreover, we’ll extend our project by including a new app designed for micro frontend integration within our workspace, thus laying the foundation for enhanced code reuse and collaboration.</p>



<p>**2. Computational Cache for Building Artifacts:** <br> Nx provides caching mechanisms that can significantly speed up the build process. Cached artifacts can be reused during local builds and within the PR/main processes, reducing build times and improving developer productivity.</p>



<p>**3. Dependency Graph and Management:** <br> Nx provides tools to visualize the dependency graph between different projects, making it easier to understand how different components are interconnected. This visibility helps in making informed decisions about code changes and minimizes unintended side effects.</p>



<p>**4. Better Developer Experience:** <br> Nx workspace tools offer features like code generation, code linting, testing, and more, all integrated within the mono repo setup. This comprehensive tooling enhances the overall developer experience and makes it easier to manage and develop different parts of the project.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<p><strong>Let the work begin</strong> </p>



<p>I was thrilled to kickstart our Nx journey. One of my initial tasks was to set up the workspace, which, fortunately, didn’t pose too many challenges. The only missing piece in our project was ESLint, which did require some time and effort to address. However, I welcomed the challenge, and by the end of the day, we had made significant progress.</p>



<p>As we continue our journey of adopting Nx, local caching remains my favorite feature.</p>



<p> I hope this article has been helpful, especially for those of you dealing with complex architectures, particularly when developing web components and creating multiple bundles for integration. Nx proves to be a valuable solution.</p>



<p>So far, we’ve developed two applications and five libraries, achieving a remarkable 85% to 100% unit test coverage for all new code. We’re still exploring the full range of possibilities that Nx offers, and I’ll be delighted to provide updates as we make progress.</p>



<hr class="wp-block-separator has-alpha-channel-opacity">



<p><strong>Conclusion</strong> </p>



<p>I’d like to emphasize that Nx isn’t limited to Angular; it’s also prominent in the React world. While it’s particularly popular in multi-team environments, my experience showcases another compelling use case. </p>



<p>Having this versatile tool in your toolbox can significantly boost your career prospects. Consider diving deeper into Nx, and advocate for its use in your workplace or project, and you’ll discover that it could be the key to unlocking your next career advancement. Thank you for joining me on this Nx journey, and here’s to the exciting opportunities it brings!</p>



<hr class="wp-block-separator has-alpha-channel-opacity">
</body>The post <a href="https://www.katesky.com/2023/10/11/streamlining-application-development-nx-monorepos-transformative-impact-for-angular-developers/">Streamlining Application Development: Nx Monorepo’s Transformative Impact for Angular Developers.</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">277</post-id>	</item>
		<item>
		<title>Nested arrays, arrays with nested dolls as an example</title>
		<link>https://www.katesky.com/2022/12/21/nested-arrays-arrays-with-nested-dolls-as-an-example/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nested-arrays-arrays-with-nested-dolls-as-an-example</link>
					<comments>https://www.katesky.com/2022/12/21/nested-arrays-arrays-with-nested-dolls-as-an-example/#comments</comments>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Wed, 21 Dec 2022 02:09:30 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=266</guid>

					<description><![CDATA[<p>This is my attempt to help a new developer understand how nested arrays opperate. A nested array can be thought of like a set of nested dolls, where each doll is contained within another doll. This array can be thought of as <br /><a href="https://www.katesky.com/2022/12/21/nested-arrays-arrays-with-nested-dolls-as-an-example/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2022/12/21/nested-arrays-arrays-with-nested-dolls-as-an-example/">Nested arrays, arrays with nested dolls as an example</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<p>This is my attempt to help a new developer understand how nested arrays opperate.</p>



<p>A nested array can be thought of like a set of nested dolls, where each doll is contained within another doll.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
[
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

</pre></div>


<p>This array can be thought of as a set of three nested dolls, where the first doll contains the array <code>[1, 2, 3]</code>, the second doll contains the array <code>[4, 5, 6]</code>, and the third doll contains the array <code>[7, 8, 9]</code>.</p>



<p>Each of these inner arrays is itself an array, and so we can think of them as smaller dolls contained within the larger dolls. For example, the first doll (which contains the array <code>[1, 2, 3]</code>) can be thought of as containing three smaller dolls, one for each element in the array.</p>



<p>We can continue this process of nesting to any level. For example, we could have an array like this:</p>



<p>For example, consider the following array:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
[
  [
    [1, 2],
    [3, 4]
  ],
  [
    [5, 6],
    [7, 8]
  ]
]

</pre></div>


<p>This array can be thought of as a set of two nested dolls, where the first doll contains the array <code>[[1, 2], [3, 4]]</code> and the second doll contains the array <code>[[5, 6], [7, 8]]</code>. Each of these inner arrays is itself an array, and so we can think of them as smaller dolls contained within the larger dolls. The innermost arrays (<code>[1, 2]</code> and <code>[3, 4]</code>) can be thought of as the smallest dolls in the set.</p>



<p>Here is an example of how you can search for elements within an array in JavaScript:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// Search for the number 3 in the array
const index = numbers.indexOf(3);
console.log(index);  // Output: 2 (the index of 3 in the array)

// Search for the number 10 in the array
const index = numbers.indexOf(10);
console.log(index);  // Output: -1 (10 is not in the array)

</pre></div>


<p>In this example, we have an array of numbers called <code>numbers</code>. We use the <code>indexOf()</code> method to search for the number <code>3</code> in the array. This method returns the index of the element in the array, or <code>-1</code> if the element is not found.</p>



<p>So, when we search for the number <code>3</code>, the <code>indexOf()</code> method returns <code>2</code>, which is the index of <code>3</code> in the <code>numbers</code> array. When we search for the number <code>10</code>, the <code>indexOf()</code> method returns <code>-1</code>, indicating that <code>10</code> is not in the array.</p>



<p>There are also other ways to search for elements within an array in JavaScript. For example, you can use the <code>includes()</code> method to check if an element is present in an array:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// Check if the array includes the number 3
const includesThree = numbers.includes(3);
console.log(includesThree);  // Output: true

// Check if the array includes the number 10
const includesTen = numbers.includes(10);
console.log(includesTen);  // Output: false

</pre></div>


<p>Here is an example of how you can search for elements within a nested array in JavaScript:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

// Search for the number 3 in the nested array
for (const innerArray of numbers) {
  const index = innerArray.indexOf(3);
  if (index !== -1) {
    console.log(`Found 3 at index ${index} of inner array ${innerArray}`);
  }
}

// Output: "Found 3 at index 2 of inner array [1, 2, 3]"

</pre></div>


<p>In this example, we have a nested array called <code>numbers</code>, which contains three inner arrays: <code>[1, 2, 3]</code>, <code>[4, 5, 6]</code>, and <code>[7, 8, 9]</code>. We use a <code>for...of</code> loop to iterate over each of the inner arrays, and we use the <code>indexOf()</code> method to search for the number <code>3</code> within each inner array.</p>



<p>If the <code>indexOf()</code> method returns a value other than <code>-1</code>, it means that <code>3</code> was found within the inner array. In this case, we log a message indicating the index at which <code>3</code> was found and the inner array in which it was found.</p>



<p>You can use a similar approach to search for elements within nested arrays at any level of nesting. For example, you could use a nested loop to iterate over each element within each inner array, and so on.</p>



<p>Here is an example of how you can use a recursive function to search for an element within a nested array in JavaScript:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
function findElement(element, array) {
  for (const item of array) {
    if (Array.isArray(item)) {
      // If the current item is an array, recursively search for the element within that array
      const result = findElement(element, item);
      if (result) {
        // If the element was found, return the result
        return result;
      }
    } else if (item === element) {
      // If the current item is the element we are searching for, return its index
      return array.indexOf(item);
    }
  }

  // If the element was not found, return null
  return null;
}

const numbers = [[1, 2, 3], [4, 5, [6, 7]], [8, 9]];

// Search for the number 7 in the nested array
const index = findElement(7, numbers);
console.log(index);  // Output: "Found 7 at index [1, 1, 1]"

</pre></div>


<p>In this example, we have defined a function called <code>findElement()</code> that takes an element and an array as arguments. The function uses a <code>for...of</code> loop to iterate over the elements in the array, and it checks whether each element is itself an array.</p>



<p>If the element is an array, the function calls itself recursively with the element and the array as arguments. This process continues until an element is found that is not an array, at which point the function checks whether the element is the element we are searching for. If it is, the function returns the index of the element within the array. If the element is not found, the function returns <code>null</code>.</p>



<p>In the example above, we use the <code>findElement()</code> function to search for the number <code>7</code> within the nested array <code>numbers</code>. The function returns <code>[1, 1, 1]</code>, which indicates that <code>7</code> was found at index <code>1</code> within the second inner array, which is itself at index <code>1</code> within the <code>numbers</code> array.</p>



<p>Here is an example of how you can use the <code>flat()</code> method to flatten a nested array and search for an element within it using the <code>indexOf()</code> method, which can provide a faster search for large arrays:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const numbers = [[1, 2, 3], [4, 5, [6, 7]], [8, 9]];

// Flatten the nested array using the flat() method
const flatNumbers = numbers.flat();

// Search for the number 7 in the flattened array
const index = flatNumbers.indexOf(7);
console.log(index);  // Output: 5 (the index of 7 in the flattened array)

</pre></div>


<p>In this example, we have a nested array called <code>numbers</code> that contains three inner arrays: <code>[1, 2, 3]</code>, <code>[4, 5, [6, 7]]</code>, and <code>[8, 9]</code>. We use the <code>flat()</code> method to flatten the array and create a new, one-dimensional array called <code>flatNumbers</code>.</p>



<p>We can then use the <code>indexOf()</code> method to search for the number <code>7</code> within the flattened array. This method returns the index of the element in the array, or <code>-1</code> if the element is not found. In this case, the method returns <code>5</code>, which is the index of <code>7</code> in the flattened array.</p>



<p>Using the <code>flat()</code> method and the <code>indexOf()</code> method can provide a faster search for large arrays, as the <code>flat()</code> method flattens the array in place and the <code>indexOf()</code> method performs a linear search through the array.</p>



<p>It is important to use optimal algorithm for searching nested arrays.</p>



<p>Using an optimal algorithm for searching nested arrays is important because it can help to reduce the time and computational resources required to find an element within the array. This can be particularly important when working with large arrays, as the time and resources required to search the array can increase significantly with the size of the array.</p>



<p>There are several algorithms that can be used to search nested arrays, each with its own trade-offs in terms of efficiency and complexity. For example, a linear search through the array (such as using the <code>indexOf()</code> method) can be relatively simple to implement, but it may not be the most efficient option for large arrays. On the other hand, more complex algorithms, such as binary search, can be more efficient but may require more implementation effort.</p>



<p>It is generally a good idea to choose an algorithm that is both efficient and easy to implement, depending on the specific requirements of your application. For example, if you are working with a small array that does not need to be searched frequently, a simple linear search may be sufficient. However, if you are working with a large array that needs to be searched frequently, you may want to consider using a more efficient algorithm.</p>



<pre class="wp-block-preformatted"></pre>



<pre class="wp-block-preformatted"></pre>
</body>The post <a href="https://www.katesky.com/2022/12/21/nested-arrays-arrays-with-nested-dolls-as-an-example/">Nested arrays, arrays with nested dolls as an example</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.katesky.com/2022/12/21/nested-arrays-arrays-with-nested-dolls-as-an-example/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">266</post-id>	</item>
		<item>
		<title>Data polling with ngrx effect and how to unit test it</title>
		<link>https://www.katesky.com/2022/12/20/data-polling-with-ngrx-effect-and-how-to-unit-test-it/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=data-polling-with-ngrx-effect-and-how-to-unit-test-it</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Tue, 20 Dec 2022 18:30:11 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[effects]]></category>
		<category><![CDATA[kate sky]]></category>
		<category><![CDATA[ngrx]]></category>
		<category><![CDATA[state management]]></category>
		<category><![CDATA[TestScheduler]]></category>
		<category><![CDATA[unit tests]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=260</guid>

					<description><![CDATA[<p>I just finished implementing data polling using ngrx effects. For those unfamiliar with ngrx, it is a popular library for implementing the Redux pattern in Angular applications. To implement data polling with ngrx effects, you can create an effect that listens for <br /><a href="https://www.katesky.com/2022/12/20/data-polling-with-ngrx-effect-and-how-to-unit-test-it/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2022/12/20/data-polling-with-ngrx-effect-and-how-to-unit-test-it/">Data polling with ngrx effect and how to unit test it</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<p>I just finished implementing data polling using ngrx effects. For those unfamiliar with ngrx, it is a popular library for implementing the Redux pattern in Angular applications.</p>



<p>To implement data polling with ngrx effects, you can create an effect that listens for a specific action, such as a <code>POLL_DATA</code> action. When this action is dispatched, the effect can perform an HTTP request to retrieve the data from a remote server, and then dispatch a new action with the data.</p>



<p>You can use the <code>@Effect</code> decorator to create an effect that listens for specific actions. The <code>@Effect</code> decorator takes an options object as an argument, which allows you to specify the action that the effect should listen for and the effect’s behavior.</p>



<p>For example, you might create an effect that listens for the <code>POLL_DATA</code> action and performs an HTTP request to retrieve the data like this:</p>


<div class="wp-block-syntaxhighlighter-code code"><pre class="brush: jscript; highlight: [1]; title: ; notranslate">
@Injectable()
export class PollingEffects {
  pollData$: Observable&lt;Action&gt; = this.actions$.pipe(
    ofType(POLL_DATA),
    switchMap(() =&gt;
      this.http.get('/api/data').pipe(
        map((data) =&gt; ({ type: DATA_RECEIVED, payload: data })),
        catchError(() =&gt; of({ type: DATA_REQUEST_FAILED }))
      )
    )
  );
}


</pre></div>


<p>This effect listens for the <code>POLL_DATA</code> action and then performs an HTTP request using the <code>HttpClient</code> service. If the request is successful, it dispatches a <code>DATA_RECEIVED</code> action with the received data as the payload. If the request fails, it dispatches a <code>DATA_REQUEST_FAILED</code> action.</p>



<p>To ensure that the data is polled at regular intervals, you can use the <code>interval</code> operator from the RxJS library. You can modify the effect above to poll the data every 10 seconds like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
@Injectable()
export class PollingEffects {
  pollData$: Observable&lt;Action&gt; = this.actions$.pipe(
    ofType(POLL_DATA),
    switchMap(() =&gt; interval(10000)),
    switchMap(() =&gt;
      this.http.get('/api/data').pipe(
        map((data) =&gt; ({ type: DATA_RECEIVED, payload: data })),
        catchError(() =&gt; of({ type: DATA_REQUEST_FAILED }))
      )
    )
  );
}

</pre></div>


<p>In this modified version of the effect, the <code>interval</code> operator is used to emit a value every 10 seconds (10000 milliseconds). The effect then uses the <code>switchMap</code> operator to perform an HTTP request every time the interval emits a value.</p>



<p>To stop the data polling, you can simply dispatch a new action that the effect can listen for and respond to.</p>



<p>For example, you might create a <code>STOP_POLLING</code> action that the effect can listen for and use to stop polling the data. You can modify the effect above to stop polling when the <code>STOP_POLLING</code> action is dispatched like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
@Injectable()
export class PollingEffects {
  pollData$: Observable&lt;Action&gt; = this.actions$.pipe(
    ofType(POLL_DATA),
    switchMap(() =&gt;
      interval(10000).pipe(takeUntil(this.actions$.pipe(ofType(STOP_POLLING))))
    ),
    switchMap(() =&gt;
      this.http.get('/api/data').pipe(
        map((data) =&gt; ({ type: DATA_RECEIVED, payload: data })),
        catchError(() =&gt; of({ type: DATA_REQUEST_FAILED }))
      )
    )
  );
}
</pre></div>


<p>In this modified version of the effect, the <code>takeUntil</code> operator is used to stop the data polling when the <code>STOP_POLLING</code> action is dispatched. The <code>takeUntil</code> operator takes an observable as an argument and completes the source observable (in this case, the <code>interval</code> observable) when the argument observable emits a value.</p>



<p>To use this modified effect, you can dispatch the <code>POLL_DATA</code> action to start polling and the <code>STOP_POLLING</code> action to stop polling.</p>



<h4 class="wp-block-heading">To create a unit test for the data polling effect using the TestScheduler from the RxJS library, you can use the following steps: </h4>



<p>First you have to modify your effect to use asyncScheduler like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
@Injectable()
export class PollingEffects {
  pollData$: Observable&amp;lt;Action&gt; = this.actions$.pipe(
    ofType(POLL_DATA),
    switchMap(() =&gt;
      interval(10000, asyncScheduler).pipe(
        takeUntil(this.actions$.pipe(ofType(STOP_POLLING)))
      )
    ),
    switchMap(() =&gt;
      this.http.get('/api/data').pipe(
        map((data) =&gt; ({ type: DATA_RECEIVED, payload: data })),
        catchError(() =&gt; of({ type: DATA_REQUEST_FAILED }))
      )
    )
  );
}

</pre></div>


<p>In this modified version of the effect, the <code>interval</code> operator is called with the <code>asyncScheduler</code> as the second argument. This causes the interval to use the <code>asyncScheduler</code> to schedule its emissions.</p>



<p>The <code>asyncScheduler</code> is a scheduler that schedules work asynchronously, using the JavaScript <code>interval</code> function. This can be useful if you want to simulate a delay in the data polling effect, or if you want to ensure that the effect is run outside the Angular zone.</p>



<p>I hope this helps clarify how to use the <code>asyncScheduler</code> with the data polling effect. Next you will add your unit tests file and follow the steps:</p>



<ol class="has-small-font-size wp-block-list">
<li>Import the <code>TestScheduler</code> from the RxJS library. The <code>TestScheduler</code> is used to control the virtual time in the test;</li>



<li>Create an instance of the <code>TestScheduler</code> and set up the test actions and expected results. To do this, you will need to define the actions that the effect should listen for and the expected results of the effect. </li>



<li>Set up the dependencies for the effect under test. This will typically include any services or dependencies that the effect uses, such as the <code>HttpClient</code> service. You can use mock implementations of these dependencies to control their behavior in the test.</li>



<li>Create an instance of the effect under test and pass in the dependencies.</li>



<li>Pass <code>TestScheduler</code> instance into the effect that is under test. This will execute the effect with a virtual timer.</li>
</ol>



<p>Here is an example of a unit test for the data polling effect using the TestScheduler:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
@Injectable()
export class PollingEffects {

    pollData$ = createEffect(() =&gt; ({ scheduler = asyncScheduler} = {}) =&gt;
    this.actions$.pipe(
      ofType(POLL_DATA),
      switchMap(() =&gt; interval(10000, asyncScheduler).pipe(
        takeUntil(this.actions$.pipe(ofType(STOP_POLLING)))
      )),
      switchMap(() =&gt; this.http.get('/api/data').pipe(
        map(data =&gt; ({ type: DATA_RECEIVED, payload: data })),
        catchError(() =&gt; of({ type: DATA_REQUEST_FAILED }))
      ))
    )
  );

}

</pre></div>


<p>To use the <code>createEffect</code> function from the ngrx library with the data polling effect, you can modify the effect like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">

</pre></div>


<p>The <code>createEffect</code> function takes a function that returns an observable as an argument, and returns an observable of actions. The function that is passed to <code>createEffect</code> should contain the logic for the effect.</p>



<p>In this modified version of the effect, the <code>createEffect</code> function is used to wrap the logic for the effect in a way that is compatible with the ngrx store. The effect listens for the <code>POLL_DATA</code> action and performs an HTTP request to retrieve the data every 10 seconds (10000 milliseconds) using asyncScheduler.  If the request is successful, it dispatches a <code>DATA_RECEIVED</code> action with the received data as the payload. If the request fails, it dispatches a <code>DATA_REQUEST_FAILED</code> action.</p>



<p>I hope this helps clarify how to use the <code>createEffect</code> function with the data polling effect. </p>



<p></p>



<p>Using ngrx effects to implement data polling is a straightforward process. Essentially, you can create an effect that listens for a specific action, such as a <code>POLL_DATA</code> action, and performs an HTTP request to retrieve data from a remote server. The effect can then dispatch a new action, such as a <code>DATA_RECEIVED</code> action, with the received data as the payload.</p>



<p>To stop the data polling, you can simply dispatch a new action, such as a <code>STOP_POLLING</code> action, that the effect can listen for and use to stop the data polling process.</p>



<p>Unit testing this effect is a bit tricky but you got it!</p>



<p>Hope all the code examples help you!</p>



<p>Hope you enjoyed this article.</p>



<p></p>



<p></p>



<pre class="wp-block-preformatted"></pre>
</body>The post <a href="https://www.katesky.com/2022/12/20/data-polling-with-ngrx-effect-and-how-to-unit-test-it/">Data polling with ngrx effect and how to unit test it</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">260</post-id>	</item>
		<item>
		<title>ng-conf 2022</title>
		<link>https://www.katesky.com/2022/12/12/ng-conf-2022/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ng-conf-2022</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Mon, 12 Dec 2022 17:48:21 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=251</guid>

					<description><![CDATA[<p>Once, in 2022, I had the opportunity to speak at a major Angular conference, ng-conf. I was nervous but excited, as this was a huge opportunity to share my knowledge and expertise with the Angular community.As the day of the conference approached, <br /><a href="https://www.katesky.com/2022/12/12/ng-conf-2022/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2022/12/12/ng-conf-2022/">ng-conf 2022</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="640" height="360" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?resize=640%2C360&#038;ssl=1" alt="" class="wp-image-255" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?w=1561&amp;ssl=1 1561w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?resize=1024%2C576&amp;ssl=1 1024w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?resize=768%2C432&amp;ssl=1 768w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?resize=1536%2C864&amp;ssl=1 1536w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2022/12/IMG_5391-2-edited.jpg?w=1280&amp;ssl=1 1280w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>



<p>Once, in 2022, I had the opportunity to speak at a major Angular conference, ng-conf. I was nervous but excited, as this was a huge opportunity to share my knowledge and expertise with the Angular community.<br>As the day of the conference approached, I spent hours preparing my presentation and practicing delivery. I wanted to ensure that I could convey ideas clearly and provide valuable insights to the audience.<br>I was so nervous on the day of the conference, but before getting to the stage, I told myself that I would do my best, no matter what happened. I took a deep breath and began my presentation, explaining the state management features of Angular and how they could be used to build powerful and efficient web applications.</p>



<p>As I presented on stage, I could see my team sitting in the front row, smiling and giving me encouraging nods. I felt a surge of confidence knowing that they were there to support me.<br>During my presentation, I could see my team nodding along, clearly impressed by my knowledge and expertise. I felt grateful to have such a supportive team behind me.<br>After my presentation, my team came up to me and congratulated me on a job well done. They praised my hard work and dedication, and I felt proud to be part of such a supportive and talented team.<br>Overall, having my team there to support me made the experience of speaking at the conference even more special and memorable. I am grateful for their support and encouragement, and I know that I couldn’t have done it without them!</p>



<p>The audience listened intently, nodding along as I spoke. I even had some jokes that made people laugh. I could see that they were interested in what I had to say, and I felt a sense of pride and accomplishment as I finished my presentation.<br>After the conference, I received many positive comments and feedback from attendees impressed by my knowledge and expertise.</p>



<p>The best feedback I got was from other women who were inspired to see a mother of 5 children on the biggest stage of her life giving a presentation on a very technical subject. They told me, “we know that it’s possible now; if you did it, then any woman can.”</p>



<p>I felt grateful for the opportunity to speak at the conference and inspire women, and I was already looking forward to the next one.</p>



<p>As a woman in the tech industry, I am well aware of the challenges and obstacles that many women face when pursuing careers in technology and programming. That’s why I hope to inspire more women to become programmers through my work and my involvement in the Angular community.<br>I believe that the tech industry would benefit greatly from having more diversity and inclusion, and I believe that women have a lot to offer in terms of their skills and perspectives.<br>I want to show other women that it is possible to succeed in the tech industry, and that they can overcome any obstacles and challenges that they may face along the way.</p>



<p><br>My mission is to help create a more diverse and inclusive tech industry by having more women who code.</p>
</body>The post <a href="https://www.katesky.com/2022/12/12/ng-conf-2022/">ng-conf 2022</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">251</post-id>	</item>
		<item>
		<title>Better ways to share data between components.</title>
		<link>https://www.katesky.com/2021/02/18/better-ways-to-share-data-between-components/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=better-ways-to-share-data-between-components</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Thu, 18 Feb 2021 09:25:00 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=218</guid>

					<description><![CDATA[<p>Sharing data in the Angular application When it comes to sharing data between components in an Angular application we have to remember that there more than one right way to do it! Let’s go over some assumptions, rules, and considerations for this <br /><a href="https://www.katesky.com/2021/02/18/better-ways-to-share-data-between-components/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2021/02/18/better-ways-to-share-data-between-components/">Better ways to share data between components.</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<h3 class="wp-block-heading">Sharing data in the Angular application</h3>



<p>When it comes to sharing data between components in an Angular application we have to remember that there more than one right way to do it!</p>



<p> Let’s go over some assumptions, rules, and considerations for this article.</p>



<p><strong>Consider</strong>: Follow a container presenter pattern. Check out my video on this <a href="https://youtu.be/d4fU0A0_oCI" target="_blank" rel="noreferrer noopener" title="Youtube link to AngualrAir meetup">here</a>.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<div class="jetpack-video-wrapper"><iframe title="AngularAir - Clean code with Container Presenter Pattern with Kate Sky" width="640" height="360" src="https://www.youtube.com/embed/d4fU0A0_oCI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
</div></figure>



<p>Your components have as little responsibility as possible; whether it is to get data from the server or just display it. </p>



<p>You create dumb components whenever possible.</p>



<p>You keep your dependency injections in the components to a minimum.</p>



<p>You abstract business logic to the services.</p>



<p><strong>Assumptions</strong>: You don’t always have the luxury of adding a state management library to your application. </p>



<p>I used NGRX and I know that it is a complex library and if the whole team is not on board to use it, then your code becomes a mish-mash of different approaches. </p>



<p>Get the whole team to commit to a state management library or go with another approach like the one described here.</p>



<p><strong>Rules</strong>: Keep application performance at the top of the priority list.</p>



<p>Your code has to be clean and easy to read and maintain.</p>



<h2 class="wp-block-heading">Say No to bubbling up events.</h2>



<p>Here is an example of 3 components that all produce data. They have no access to the data they create. Events bubble up to the app.component. </p>



<p><strong>I want to show you what NOT to do!</strong></p>



<p>checkout StackBlitz:</p>



<p><a href="https://stackblitz.com/github/katesky/messages-sent-app" target="_blank" rel="noreferrer noopener" title="bad code">https://stackblitz.com/github/katesky/messages-sent-app</a></p>



<p>Next up is code where we will add a service that will manage our data and it will be shared with all of our components.</p>



<h2 class="wp-block-heading">Use service with a subject</h2>



<p>git checkout with-service or go to code here –&gt; <a href="https://stackblitz.com/github/katesky/messages-sent-app/tree/with-service" target="_blank" rel="noreferrer noopener" title="new branch">new branch</a></p>



<p>We will create a service that will hold a list of our data in a private BehaviorSubject of type an array of strings.</p>



<p>We will add a public observable of that BehaviorSubject to our service.</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="640" height="164" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?resize=640%2C164&#038;ssl=1" alt="" class="wp-image-219" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?resize=1024%2C262&amp;ssl=1 1024w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?resize=300%2C77&amp;ssl=1 300w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?resize=768%2C196&amp;ssl=1 768w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?resize=1536%2C393&amp;ssl=1 1536w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?w=1548&amp;ssl=1 1548w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic1.png?w=1280&amp;ssl=1 1280w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>



<p>Now we can add a function that will mutate our data.</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="640" height="229" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?resize=640%2C229&#038;ssl=1" alt="" class="wp-image-220" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?resize=1024%2C366&amp;ssl=1 1024w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?resize=300%2C107&amp;ssl=1 300w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?resize=768%2C275&amp;ssl=1 768w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?resize=1536%2C549&amp;ssl=1 1536w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?w=1694&amp;ssl=1 1694w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic2.png?w=1280&amp;ssl=1 1280w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>



<p>We now have a central area where our data is held.</p>



<p>It can be shared across all of our components and there are no events that have to be emitted up to the parents’ components.</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="640" height="283" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?resize=640%2C283&#038;ssl=1" alt="" class="wp-image-221" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?resize=1024%2C453&amp;ssl=1 1024w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?resize=300%2C133&amp;ssl=1 300w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?resize=768%2C340&amp;ssl=1 768w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?resize=1536%2C680&amp;ssl=1 1536w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?w=1564&amp;ssl=1 1564w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic3.png?w=1280&amp;ssl=1 1280w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>



<p>Now that our application is truly reactive we can change out changeDetection to OnPush. <a href="https://angular.io/api/core/ChangeDetectionStrategy#members" target="_blank" rel="noreferrer noopener">More info on it here.</a></p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="640" height="366" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?resize=640%2C366&#038;ssl=1" alt="" class="wp-image-222" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?resize=1024%2C586&amp;ssl=1 1024w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?resize=300%2C172&amp;ssl=1 300w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?resize=768%2C440&amp;ssl=1 768w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?resize=1536%2C879&amp;ssl=1 1536w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?w=1562&amp;ssl=1 1562w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic4.png?w=1280&amp;ssl=1 1280w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>



<p>Change template to using async pipe. <a href="https://angular.io/api/common/AsyncPipe" target="_blank" rel="noreferrer noopener" title="async pipe">Read about it here!</a></p>



<p>We can use data$ in all other components the same way as here:</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="640" height="180" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic5.png?resize=640%2C180&#038;ssl=1" alt="" class="wp-image-223" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic5.png?resize=1024%2C288&amp;ssl=1 1024w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic5.png?resize=300%2C84&amp;ssl=1 300w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic5.png?resize=768%2C216&amp;ssl=1 768w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2021/02/pic5.png?w=1168&amp;ssl=1 1168w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>



<p>Checkout Stackblitz with code complete:</p>



<p><a href="https://stackblitz.com/github/katesky/messages-sent-app/tree/with-service" target="_blank" rel="noreferrer noopener" title="good code">https://stackblitz.com/github/katesky/messages-sent-app/tree/with-service</a></p>



<p>I hope this article was usefull for you. </p>



<p>I was able to show you something new and you will avoid some of the mistakes I made when I got started with Angular.</p>



<p>One of my passions is to be able to inspire mothers to get started in technology sector.  I am a programmer with over 20 years of experance in IT.</p>



<p>I am also a mother of 5 children. I hope one day my daughters will be inspired by my story to go into STEM.</p>



<p>Till next time!</p>



<p>Kate Sky.</p>
</body>The post <a href="https://www.katesky.com/2021/02/18/better-ways-to-share-data-between-components/">Better ways to share data between components.</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">218</post-id>	</item>
		<item>
		<title>Angular NGRX enabling DevTools at runtime</title>
		<link>https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=angular-ngrx-enabling-devtools-at-runtime</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Mon, 22 Jun 2020 20:51:26 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[devtool]]></category>
		<category><![CDATA[ngrx]]></category>
		<category><![CDATA[redux]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=169</guid>

					<description><![CDATA[<p>Angular NGRX enabling DevTools at runtime In this article, I will cover a problem that I was working on in one of my projects. With help from the NGRX team, I was able to solve it.  Shot-out to @brandontroberts , @tim_deschryver, @AlexOkrushko! <br /><a href="https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/">Angular NGRX enabling DevTools at runtime</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<h2 class="wp-block-heading">Angular NGRX enabling DevTools at runtime</h2>



<p>In this article, I will cover a problem that I was working on in one of my projects. With help from the NGRX team, I was able to solve it.  Shot-out to <a href="https://twitter.com/brandontroberts">@brandontroberts</a> , <a href="https://twitter.com/tim_deschryver">@tim_deschryver</a>, <a href="https://twitter.com/AlexOkrushko">@AlexOkrushko</a>!</p>



<p>I hope it helps you when using NGRX, and you can also add it as part of your development process. </p>



<h3 class="wp-block-heading">Problem:</h3>



<p>I wanted to be able to enable DevTools at runtime. The reason I want to do that is to be able to let users report his/her application experience and especially the problems they are experiencing. </p>



<p>In other words, enable debugging reporting on the fly using NGRX framework.</p>



<h3 class="wp-block-heading">Solution:</h3>



<p>This article will be useful if you love Redux DevTools, but you don’t have them enabled in Production.</p>



<p>You would like to have your application to be able to switch to the reporting mode, even in Production.</p>



<p>I will cover the following steps:</p>



<ol class="wp-block-list"><li>Adding a lazy-loaded Feature Module</li><li>Dispatching an effect to create a StoreDevtoolsModule at runtime</li><li>Extras:<ol><li>Use hidden F1 key to enable a link for debugging. </li><li>Enable third party logging/debugging tools  </li></ol></li></ol>



<h3 class="wp-block-heading">Implementation:</h3>



<p>We start by adding a feature; we will call it ‘debug’.  </p>



<p>It will contain:</p>



<ol class="wp-block-list"><li> debug.action – We will use an NGRX action from this file to dispatch from the component.</li><li>debug.component. We will use Debug component to load our feature via a new route we will add to app.module. </li><li>debug.module – We will lazy-load this module that in the app.module, and it will contain a route to the component</li><li>app.module – Register a new feature with a lazy-loaded route</li><li>dev-tools.module – Module that will inject the StoreDevTools to kick-of the Redux tools registration from this module.</li><li>debug.effect – We will use this NGRX effect to catch an action dispatched. This effect will be responsible for the runt-time enabling of the dev tools.</li><li>root-store.module – Register new Effect in RootModule</li><li>app.componet – Add a hiddent button that can be turned visible by F1- hot key</li></ol>



<h4 class="wp-block-heading">debug.action.ts</h4>



<p>Add a new action to be dispatch to the store about the state change. </p>



<p>We prefix the type of the action with the name of the page that will dispatch this action. </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [3]; title: ; notranslate">
import { createAction } from '@ngrx/store';

export const enableDebug = createAction('[Debug Page] enable');
</pre></div>


<h4 class="wp-block-heading">debug.component.ts</h4>



<p>Add a new component. If you like, you can keep template and styles inline. Both are not used in this setup, so can easily be excluded. </p>



<p>I have an empty template because its not needed.</p>



<p>When component is loaded it will dispatch an action that will enable DevTools (line 14).  Effect is below, I promise!</p>



<p><strong>in terminal:</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
ng generate component debug--inlineTemplate=true --inlineStyle=true
</pre></div>


<p><strong>in new file debug.component.ts</strong>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [14]; title: ; notranslate">
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { RootState } from '../+state/root.selectors';
import { enableDebug } from './debug.actions';

@Component({
  template: ``,
  selector: 'app-debug'
})
export class DebugComponent implements OnInit {
  constructor(private readonly store: Store&lt;RootState&gt;) {}

  ngOnInit(): void {
    this.store.dispatch(enableDebug());
  }
}

</pre></div>


<h4 class="wp-block-heading">debug.module.ts</h4>



<p>This module is lazy-loaded so it will be registering the child routes.</p>



<p><strong>debug.module.ts</strong>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [6]; title: ; notranslate">
import { NgModule } from '@angular/core';
import { DebugComponent } from './debug.component';
import { RouterModule } from '@angular/router';
@NgModule({
  imports: [ 
      RouterModule.forChild([{ path:'',component:DebugComponent}])
  ],
  declarations: [DebugComponent],
  exports: [DebugComponent]

})
export class DebugModule {
  constructor(){}
}

</pre></div>


<h4 class="wp-block-heading">app.module.ts</h4>



<p>This module we will add a new route and lazy-load it with a feature module. </p>



<p>This is a code-snipet , so if you want to see full code check out my repository.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [4,5,6]; title: ; notranslate">
{
    path: 'debug',
    loadChildren: () =&gt;
    import('./debug/debug.module').then(
      m =&gt; m.DebugModule
    )
      
  },
</pre></div>


<h4 class="wp-block-heading">dev-tools.module.ts</h4>



<p>This module will be compiled and created in the effect. </p>



<p>On line 14th you can refresh the tools. I didn’t see much of a difference in value having it execute.</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [13,16]; title: ; notranslate">
import { NgModule } from '@angular/core';
import { StoreDevtoolsModule, StoreDevtools } from '@ngrx/store-devtools';
@NgModule({
  imports: [
    StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: true
    })
  ]
})
export class DevToolsModule {
  constructor(private storeDevtools: StoreDevtools) {
    // storeDevtools.refresh();
  }
} 

</pre></div>


<h4 class="wp-block-heading">debug.effect.ts</h4>



<p>Effect class is responsible for reacting to the action dispatched from the component.  It filters out actions that it is subscribing to and when enableDebug is dispatched, effect is using ‘exhaustMat’ operator to make sure that if same action is dispatched it will continue to execute. In other words dropping incoming request.</p>



<p>Next it uses injected compiler object to compile dev-tools.module and creates it on lines 21-24.</p>



<p>Once that is completed, we have devtools enabled and redux tools can be used to track our state changes.</p>



<p>We know that we will have a manual mechanism of turning debugging option on so we can redirect our user back to that location. In this case it’s root of the application or home. So the changeLink action is returned via this effect.</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [21,22,23,24]; title: ; notranslate">
import { Injectable, Compiler, Injector } from '@angular/core';
import { createEffect, Actions, ofType } from '@ngrx/effects';

import * as DebugActions from './debug.actions';
import { exhaustMap } from 'rxjs/operators';
import { DevToolsModule } from './dev-tools-module'; 
import { changeLink } from '../+state/root.actions';

@Injectable()
export class DebugEffects {
  constructor(
    private actions$: Actions,
    private compiler: Compiler,
    private injector: Injector
  ) {}

  debugAction$ = createEffect(() =&gt;
    this.actions$.pipe(
      ofType(DebugActions.enableDebug),
      exhaustMap(async () =&gt; {
        const m = this.compiler.compileModuleSync&lt;DevToolsModule&gt;(
          DevToolsModule
        );
        m.create(this.injector); 
        return changeLink({ link: '' });
      })
    )
  );
}

</pre></div>


<p>If you checkout my repository you will see that I just imported DevToolsModule into the DebugModule for simplicity. I kept the effect for other use case in Extra#2.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [8]; title: ; notranslate">
import { NgModule } from '@angular/core';
import { DebugComponent } from './debug.component';
import { RouterModule } from '@angular/router';
import { DevToolsModule } from './dev-tools-module';
@NgModule({
  imports: [ 
      RouterModule.forChild([{ path:'',component:DebugComponent}]),
      DevToolsModule
  ],
  declarations: [DebugComponent],
  exports: [DebugComponent]

})
export class DebugModule {
  constructor(){}
  
}

</pre></div>


<h4 class="wp-block-heading">app.component.html</h4>



<p>Add anywhere you would like to include a hidden button. So next time your user is having some unexplainable issues they can hit F1 and it will become visible.</p>



<p>Can you tell I am using material components?  So if you this code make sure you import all necessary Modules for Material <a href="https://material.angular.io/components/button/api" target="_blank" rel="noreferrer noopener">here</a>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
&lt;button *ngIf="isDebugVisible" (click)="onDebug()"mat-icon-button aria-label="debug"&gt;
  &lt;mat-icon&gt;bug_report&lt;/mat-icon&gt;
&lt;/button&gt;
</pre></div>


<h4 class="wp-block-heading">app.component.ts</h4>



<p>Extra #1: As promised I will give this little trick. I added hidden button to help user discover issues and be part of the debugging process.</p>



<p>We will add a function to make our button visible with HostListener, filtering out keys. </p>



<p>Next we will add a button click event that will redirect our user to the lazy-loaded module we just setup.  </p>



<p><strong>Remember</strong>: user will be redirected back here from the debug.effect? </p>



<p>So we can turn off the button – our devtools are enabled!</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
  onDebug() {
    this.store.dispatch(changeLink({ link: 'debug' }));
    this.isDebugVisible = false;
  }
  @HostListener('document:keydown', ['$event'])
  keypress(e: KeyboardEvent) {
    if (e.key === 'F1') {
      this.isDebugVisible = true;
    }
  }
</pre></div>


<h4 class="wp-block-heading">Extras #2</h4>



<p>If you haven’t heard of LogRocket yet. Let me Introduce you. <a href="http://www.logrocket.com">www.logrocket.com</a> This is a very cool product that you can plugin to the application to see a full path of your user experience with visual snap shots.</p>



<p>How cool is that?</p>



<p>If you follow their instruction it is pretty straight forward to include and get started with in your application.</p>



<p><strong> https://app.logrocket.com/&lt;replace-with-yourcode&gt;/settings/integrations/</strong></p>



<p>It is a paid product, if you exceed the number of requests that are free! </p>



<p>But let see if we can utilize a free version by only enabling the setup from our debug lazy-loaded module dev-tools.module? </p>



<p><strong>update debug.effect.ts</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [7,26]; title: ; notranslate">
import { Injectable, Compiler, Injector } from '@angular/core';
import { createEffect, Actions, ofType } from '@ngrx/effects';

import * as DebugActions from './debug.actions';
import { exhaustMap } from 'rxjs/operators';
import { DevToolsModule, LOGROCKET_INIT_KEY } from './dev-tools-module';
import * as LogRocket from 'logrocket'; 
import { changeLink } from '../+state/root.actions';

@Injectable()
export class DebugEffects {
  constructor(
    private actions$: Actions,
    private compiler: Compiler,
    private injector: Injector
  ) {}

  debugAction$ = createEffect(() =&gt;
    this.actions$.pipe(
      ofType(DebugActions.enableDebug),
      exhaustMap(async () =&gt; {
        const m = this.compiler.compileModuleSync&lt;DevToolsModule&gt;(
          DevToolsModule
        );
        m.create(this.injector);
        LogRocket.init(LOGROCKET_INIT_KEY);
        return changeLink({ link: '' });
      })
    )
  );
}

</pre></div>


<p><strong>update dev-tool.module.ts</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [3,4,5,6,7,8,9,10,11,12,13,14,15,16,24,25,26,27,28,29,30,31]; title: ; notranslate">
import { NgModule } from '@angular/core';
import { StoreDevtoolsModule, StoreDevtools } from '@ngrx/store-devtools';
import { USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
import * as LogRocket from 'logrocket';
import createNgrxMiddleware from 'logrocket-ngrx';
import { MetaReducer, State } from '@ngrx/store'; 
import { RootState } from '../+state/root.selectors';
const logrocketMiddleware = createNgrxMiddleware(LogRocket, {});

export const metaReducers: MetaReducer&lt;any&gt;[] = [];

export function getMetaReducers(): MetaReducer&lt;RootState&gt;[] {
  return metaReducers.concat([logrocketMiddleware]);
}
export const LOGROCKET_INIT_KEY = '&lt;replace-with-your-code';

@NgModule({
  imports: [
    StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: true
    })
  ],
  providers: [
  
    {
      provide: USER_PROVIDED_META_REDUCERS,
      useFactory: getMetaReducers
    }
  ]}
)
export class DevToolsModule {
  constructor(private storeDevtools: StoreDevtools) {
    // storeDevtools.refresh();
  }
}

</pre></div>


<p>Now that we have this setup, we can see our requests are only feeding into our LogRocket account after we enabled debug!</p>



<p></p>



<p>I hope you enjoyed this article! Tweet you questions or comments <a rel="noreferrer noopener" href="https://twitter.com/intent/tweet?text=Hi,@katesky8%20%22Question/comment%20about%20your%20post%20Angular%20NGRX%20enabling%20DevTools%20at%20runtime%20%F0%9F%91%8D%F0%9F%91%8D%F0%9F%91%8D&amp;url=https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime" target="_blank">here</a>. </p>



<p>I will be glad to connect too!</p>



<p></p>



<ul class="wp-block-social-links is-layout-flex wp-block-social-links-is-layout-flex">



<li class="wp-social-link wp-social-link-twitter  wp-block-social-link"><a href="https://twitter.com/intent/tweet?text=Hi,@katesky8%20Question/comment%20about%20your%20post%20Angular%20NGRX%20enabling%20DevTools%20at%20runtime%20%F0%9F%91%8D%F0%9F%91%8D%F0%9F%91%8D&amp;url=https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime" class="wp-block-social-link-anchor"><svg width="24" height="24" viewbox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M22.23,5.924c-0.736,0.326-1.527,0.547-2.357,0.646c0.847-0.508,1.498-1.312,1.804-2.27 c-0.793,0.47-1.671,0.812-2.606,0.996C18.324,4.498,17.257,4,16.077,4c-2.266,0-4.103,1.837-4.103,4.103 c0,0.322,0.036,0.635,0.106,0.935C8.67,8.867,5.647,7.234,3.623,4.751C3.27,5.357,3.067,6.062,3.067,6.814 c0,1.424,0.724,2.679,1.825,3.415c-0.673-0.021-1.305-0.206-1.859-0.513c0,0.017,0,0.034,0,0.052c0,1.988,1.414,3.647,3.292,4.023 c-0.344,0.094-0.707,0.144-1.081,0.144c-0.264,0-0.521-0.026-0.772-0.074c0.522,1.63,2.038,2.816,3.833,2.85 c-1.404,1.1-3.174,1.756-5.096,1.756c-0.331,0-0.658-0.019-0.979-0.057c1.816,1.164,3.973,1.843,6.29,1.843 c7.547,0,11.675-6.252,11.675-11.675c0-0.178-0.004-0.355-0.012-0.531C20.985,7.47,21.68,6.747,22.23,5.924z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Twitter</span></a></li>







<li class="wp-social-link wp-social-link-twitter  wp-block-social-link"><a href="https://twitter.com/KateSky8" class="wp-block-social-link-anchor"><svg width="24" height="24" viewbox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M22.23,5.924c-0.736,0.326-1.527,0.547-2.357,0.646c0.847-0.508,1.498-1.312,1.804-2.27 c-0.793,0.47-1.671,0.812-2.606,0.996C18.324,4.498,17.257,4,16.077,4c-2.266,0-4.103,1.837-4.103,4.103 c0,0.322,0.036,0.635,0.106,0.935C8.67,8.867,5.647,7.234,3.623,4.751C3.27,5.357,3.067,6.062,3.067,6.814 c0,1.424,0.724,2.679,1.825,3.415c-0.673-0.021-1.305-0.206-1.859-0.513c0,0.017,0,0.034,0,0.052c0,1.988,1.414,3.647,3.292,4.023 c-0.344,0.094-0.707,0.144-1.081,0.144c-0.264,0-0.521-0.026-0.772-0.074c0.522,1.63,2.038,2.816,3.833,2.85 c-1.404,1.1-3.174,1.756-5.096,1.756c-0.331,0-0.658-0.019-0.979-0.057c1.816,1.164,3.973,1.843,6.29,1.843 c7.547,0,11.675-6.252,11.675-11.675c0-0.178-0.004-0.355-0.012-0.531C20.985,7.47,21.68,6.747,22.23,5.924z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Twitter</span></a></li></ul>



<p>If you would like to see a repository where I added this implementation,  follow this github link: </p>



<p><a href="https://github.com/katesky/saraphan-radio/tree/azure/apps/shell-app/src/app/debug">https://github.com/katesky/saraphan-radio/tree/azure/apps/shell-app/src/app/debug</a> </p>
</body>The post <a href="https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/">Angular NGRX enabling DevTools at runtime</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">169</post-id>	</item>
		<item>
		<title>Enterprise Application Journey</title>
		<link>https://www.katesky.com/2020/04/21/enterprise-application-journey/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=enterprise-application-journey</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Tue, 21 Apr 2020 20:42:59 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[Enterprise]]></category>
		<category><![CDATA[Monorepo]]></category>
		<category><![CDATA[Enterprise Application]]></category>
		<category><![CDATA[full-stack]]></category>
		<category><![CDATA[kate sky]]></category>
		<category><![CDATA[ngrx]]></category>
		<category><![CDATA[state management]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=137</guid>

					<description><![CDATA[<p>Angular: front-end from start to MVP by Kate Sky I am making this post as the first step in documenting my journey of building an Enterprise application for my side project. The application is in the process of going towards an MVP. This <br /><a href="https://www.katesky.com/2020/04/21/enterprise-application-journey/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2020/04/21/enterprise-application-journey/">Enterprise Application Journey</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<body>
<h3 class="wp-block-heading">Angular: front-end from start to MVP</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>by Kate Sky</p></blockquote>



<p>I am making this post as the first step in documenting my journey of building an Enterprise application for my side project.</p>



<p>The application is in the process of going towards an MVP.</p>



<p>This application is an “Uber for home services.” </p>



<p>The reason I had started this project: is to provide a value-based service while practicing and teaching others skills I had acquired over the years.</p>



<p>The objective of this post is to establish a timeline of the application going live from its infancy.</p>



<hr class="wp-block-separator">



<p>Following is the list of topics that we are going to discuss in this article:</p>



<ol class="wp-block-list"><li>Application Stack</li><li>Architectural decisions<ol style="user-select: auto;"><li>Monorepo with Nx</li><li>Domain-Driven Design with Angular</li><li>State management with NGRX </li><li>Logging with LogRocket</li><li>Authentication with Auth0</li></ol></li><li>Conclusion</li><li>Links</li></ol>



<hr class="wp-block-separator">



<h4 class="wp-block-heading">1. Application Stack</h4>



<p>WEB- Angular<br>API – .Net Core<br>DB – SQL server</p>



<hr class="wp-block-separator">



<h4 class="wp-block-heading">2. Architectural decisions</h4>



<p>For web client, I am using Angular framework.</p>



<p>My goal – to be able to scale the development of this application by having the ability to go from one team to many teams building multiple frontend and backend applications all in the same workspace. </p>



<p>I chose <a target="_blank" href="https://nx.dev/angular" rel="noreferrer noopener">NX</a>, so developers have a holistic dev experience powered by an advanced CLI (with editor plugins), capabilities for controlled code sharing, and consistent code generation.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" decoding="async" width="446" height="664" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/1.png?resize=446%2C664&#038;ssl=1" alt="" class="wp-image-139" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/1.png?w=446&amp;ssl=1 446w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/1.png?resize=202%2C300&amp;ssl=1 202w" sizes="auto, (max-width: 446px) 100vw, 446px" /></figure></div>



<hr class="wp-block-separator">



<p>Monorepos allow huge enterprise applications to be subdivided into small and maintainable libraries. I followed the best practice from the creators of NX and have added a <a rel="noreferrer noopener" style="user-select: auto;" target="_blank" href="https://www.npmjs.com/package/@angular-architects/ddd">domain-driven</a> design approach to creating the features. One of the features is the search capability for the providers that are displayed. I added a domain ‘Providers’ it contains the feature store for state management and the infrastructure where service is implemented to call the API.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>We need to first define criteria for slicing our application into individual parts and we must establish rules for communication between them.</p><cite>referenced: <a href="https://www.angulararchitects.io/aktuelles/sustainable-angular-architectures-1/">https://www.angulararchitects.io/aktuelles/sustainable-angular-architectures-1/</a></cite></blockquote>



<p></p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" decoding="async" width="463" height="379" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/2.png?resize=463%2C379&#038;ssl=1" alt="" class="wp-image-140" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/2.png?w=463&amp;ssl=1 463w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/2.png?resize=300%2C246&amp;ssl=1 300w" sizes="auto, (max-width: 463px) 100vw, 463px" /></figure></div>



<hr class="wp-block-separator">



<p>I have added <a rel="noreferrer noopener" style="user-select: auto;" target="_blank" href="https://ngrx.io/">NGRX </a>from the very beginning because I would like to have an ability to replay the user’s trip through the application, and I will be adding <a rel="noreferrer noopener" style="user-select: auto;" target="_blank" href="https://logrocket.com/">LogRocket </a>to view that path. NGRX will also help me write clean reactive components with async pipes. Root store has its own module and is at the root of the application. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Stop guessing why bugs happen. LogRocket lets you replay what users do on your site, helping you reproduce bugs and fix issues faster.</p><cite><a href="https://logrocket.com/">https://logrocket.com/</a></cite></blockquote>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" decoding="async" width="467" height="482" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/3-2.png?resize=467%2C482&#038;ssl=1" alt="" class="wp-image-143" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/3-2.png?w=467&amp;ssl=1 467w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/3-2.png?resize=291%2C300&amp;ssl=1 291w" sizes="auto, (max-width: 467px) 100vw, 467px" /></figure></div>



<hr class="wp-block-separator">



<p>Since we have 2 features now, we can see that NGRX stores for each feature are located near the domain for each feature’s library. There is separate module for each store to be able to import each feature module lazily.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" decoding="async" width="498" height="575" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/4.png?resize=498%2C575&#038;ssl=1" alt="" class="wp-image-144" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/4.png?w=498&amp;ssl=1 498w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/4.png?resize=260%2C300&amp;ssl=1 260w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure></div>



<hr class="wp-block-separator">



<p>Users have to register, and for authentication, I picked <a rel="noreferrer noopener" style="user-select: auto;" target="_blank" href="https://auth0.com/">Auth0</a>. Right now, you can see that authentication is on the root store. I have a login and logout actions that are calling the service to execute the correct code. I am using the service I download from the example provided by auth0. It still needs to be cleaned up. </p>



<p>I added a component for the callback path need for the login of the authentication. There is a CanActivate guard that is used for components that need an authorized user.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" decoding="async" width="506" height="454" src="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/5.png?resize=506%2C454&#038;ssl=1" alt="" class="wp-image-145" loading="lazy" srcset="https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/5.png?w=506&amp;ssl=1 506w, https://i0.wp.com/www.katesky.com/wp-content/uploads/2020/04/5.png?resize=300%2C269&amp;ssl=1 300w" sizes="auto, (max-width: 506px) 100vw, 506px" /></figure></div>



<hr class="wp-block-separator">



<h4 class="wp-block-heading">3 . Conclusion</h4>



<p>In conclusion, we will go through whats next.</p>



<p>I wanted to get the frontend started first and have a clear user experience throughout the application.</p>



<p>I will add the .net Core API to store the data to the database next. </p>



<p>I deployed code to GitHub pages to be able to get user feedback at the very early stages of this application.</p>



<hr class="wp-block-separator">



<h4 class="wp-block-heading">4. Links</h4>



<p>Code: <a style="user-select: auto;" href="https://github.com/katesky/saraphan-radio">https://github.com/katesky/saraphan-radio</a></p>



<p>Dev version: <a href="https://katesky.github.io/saraphan-radio/">https://katesky.github.io/saraphan-radio/</a></p>



<p>Domain: <a href="http://sarafanradio.com/">http://saraphanradio.com</a></p>



<p></p>



<p></p>
</body>The post <a href="https://www.katesky.com/2020/04/21/enterprise-application-journey/">Enterprise Application Journey</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">137</post-id>	</item>
	</channel>
</rss>
