<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Tony Shaji</title>
    <description>The latest articles on Forem by Tony Shaji (@tonyshaji).</description>
    <link>https://forem.com/tonyshaji</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1371034%2F368e1998-1384-4888-976b-09e929228d64.png</url>
      <title>Forem: Tony Shaji</title>
      <link>https://forem.com/tonyshaji</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tonyshaji"/>
    <language>en</language>
    <item>
      <title>Disabling button on api calls in Angular</title>
      <dc:creator>Tony Shaji</dc:creator>
      <pubDate>Wed, 01 Jan 2025 16:44:00 +0000</pubDate>
      <link>https://forem.com/tonyshaji/disabling-button-on-api-calls-in-angular-2n17</link>
      <guid>https://forem.com/tonyshaji/disabling-button-on-api-calls-in-angular-2n17</guid>
      <description>&lt;p&gt;While working on multiple frameworks, I have come across a common bug that occurs caused by clicking an api calling button multiple times. The issue is that the consecutive button click is causing repeated api calls. This causes unwanted operations in the database. The common solution is to disable the button before the api call and enable it after the call has been completed either by response or error.&lt;br&gt;&lt;br&gt;
The code looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;saveData(): void {
    this.isSaving = true; // Disable the button and show the spinner

    // Call the service method
    this.mockService.btnclickCheck().subscribe({
      next: (response) =&amp;gt; {
        console.log('Service response:', response);
        this.isSaving = false; // Re-enable the button
      },
      error: (error) =&amp;gt; {
        console.error('Error occurred:', error);
        this.isSaving = false; // Re-enable the button even on error
      }
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution works but this disabling and enabling needs to be added everywhere when a button calls api. The same code is being repeated everywhere for a click on button. But If the same code is repeated we should always look to extract it to a common place and decrease the clutter on the rendering part. For Angular there is an easy way to extract it to a directive and clean up the components code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Directive, ElementRef, Input } from '@angular/core';
import { EMPTY, exhaustMap, finalize, fromEvent, isObservable, Observable, of, Subscription, take } from 'rxjs';

export type ButtonHandler = (
  e?: MouseEvent
) =&amp;gt; Observable&amp;lt;unknown&amp;gt; | Promise&amp;lt;unknown&amp;gt;;

const defaultHandler: ButtonHandler = (e) =&amp;gt; EMPTY;
@Directive({
  selector: 'button[save-btn]',
  exportAs: 'saveBtn',
  host: {
    '[disabled]': ' _processing',
    '[class.loading]': '_processing',
  },
})
export class ButtonClickDirective {

  private _processing = false;
  private _sub = Subscription.EMPTY;

  @Input()
  handler: ButtonHandler = defaultHandler;

  get processing(): boolean {
    return this._processing;
  }

  constructor(private readonly btnElement: ElementRef&amp;lt;HTMLButtonElement&amp;gt;) {}

  ngAfterViewInit() {
    this._sub = fromEvent&amp;lt;MouseEvent&amp;gt;(this.btnElement.nativeElement, 'click')
      .pipe(exhaustMap((e) =&amp;gt; this.wrapHandlerInObservable(e)))
      .subscribe();
  }

  ngOnDestroy() {
    this._sub.unsubscribe();
  }

  private wrapHandlerInObservable(e: MouseEvent) {
    this._processing = true;
    const handleResult = this.handler(e);
    let obs: Observable&amp;lt;unknown&amp;gt;;
    if (isObservable(handleResult)) {
      obs = handleResult;
    } else {
      obs = of(handleResult);
    }
    return obs.pipe(
      take(1),
      finalize(() =&amp;gt; (this._processing = false))
    );
  }

}

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

&lt;/div&gt;



&lt;p&gt;Here the directive uses a fromEvent operator from RxJs to create an event on button click. The components should use this operator to chain to this event using pipe operator and call the necessary api calls. The directive has a check using exhaustmap operator that make the check if an inner observable is active. If there is an inner observable, a flag is set to true. Based on this flag value we can add visual changes like disabling button or adding a spinner to the event target which is of course the button&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;handler: any = (e:any) =&amp;gt; {
    const api = this.mockService.btnclickCheck();
    api.subscribe((res) =&amp;gt; {
      console.log(res);
    });
    return api;
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button save-btn [handler]="handler"&amp;gt;Click me!&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The api calls required to be called are added as input. In the directive empty observable is set as default value for handler input. The response from api is handled at the end such that it is always an observable. The flag is reset at the end in finalize operator. You can find the sample code here &lt;a href="https://github.com/tonyshaji/button-click-directive" rel="noopener noreferrer"&gt;https://github.com/tonyshaji/button-click-directive&lt;/a&gt;&lt;br&gt;
Now the button and it’s api call is in your component, but disabling and enabling of button or adding some spinners for that cause is moved to a directive. Making the component leaner and cleaner  &lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>rxjs</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Backpedaling in Angular: Scenarios to avoid</title>
      <dc:creator>Tony Shaji</dc:creator>
      <pubDate>Thu, 30 May 2024 11:18:06 +0000</pubDate>
      <link>https://forem.com/tonyshaji/backpedaling-in-angular-scenarios-to-avoid-1o9g</link>
      <guid>https://forem.com/tonyshaji/backpedaling-in-angular-scenarios-to-avoid-1o9g</guid>
      <description>&lt;p&gt;New gen JavaScript based frameworks like angular have been created to overcome the shortcomings of JavaScript. Often developers who are new to these frameworks implements old JavaScript code, instead of using new features of Angular. Here are some avoidable scenarios.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Avoiding Observables to use Async awaits and promises.&lt;/p&gt;

&lt;p&gt;Async await is a JavaScript feature for asynchronous operations. But angular comes with a better and more powerful library Rxjs. Async await cannot cancel the operation once it is executed while Rxjs can cancel it. Async await only supports a single emission for a call, But Rxjs can run for any number of times.&lt;/p&gt;

&lt;p&gt;When you already have a better library like Rxjs, it makes no sense to use async await. Since Angular is based on JavaScript async await will surely run on Angular. But it doesn’t mean that You should be using it. Whatever async await can do, Rxjs can do better and even more.     &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using reactive forms and template driven forms together&lt;/p&gt;

&lt;p&gt;Some developers seems to use reactive forms and template driven forms together. &lt;/p&gt;

&lt;p&gt;Reactive forms are guided by the principle of 'one-way' data binding, which involves managing the state of forms using an immutable approach. This means that changes to the form state are made in a way that prevents them from being directly modified after they are initially set. By following this approach, there is a clearer separation of concerns between the template, which defines the form structure, and the component logic, which handles form behavior and interactions. This separation enhances maintainability and readability of the codebase, making it easier to understand and maintain.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ngModel&lt;/code&gt; directive will keep track of the value typed in by the user with each key pressed, and it will also keep track of the validity state of that particular form control only. NgModel adheres to ‘two-way’ binding.&lt;/p&gt;

&lt;p&gt;While running this angular produces a warning in development mode&lt;/p&gt;

&lt;p&gt;Actually reactive forms are a better and more feature rich version of template driven form&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating common service for calling Api &lt;/p&gt;

&lt;p&gt;Angular is built over typescript which is a strongly typed language. Which means there is stricter typing rules at compile time, which implies that errors and exceptions are more likely to happen during compilation. Most of these rules affect variable assignment, function return values, procedure arguments and function calling.&lt;/p&gt;

&lt;p&gt;When common service is created for all Api calls the type is given as  any in usual cases which discards the benefits of strong typing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Not using angular cli to create new files&lt;/p&gt;

&lt;p&gt;If you doesn’t use angular cli,  there is higher chance that the naming convention is broken somewhere, making the code less readable.  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating one single module for all shared components &lt;/p&gt;

&lt;p&gt;Many developers  add all shared component to a  single module and calls it shared module. This in fact increase the load on the page and makes rendering slower. The components that are not required for the current page is loaded from the shared module. With standalone component this issue is almost solved. But in angular apps using old version this issue exists.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58ij5jakynq6io1wtprz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58ij5jakynq6io1wtprz.png" alt="Image description" width="584" height="86"&gt;&lt;/a&gt;&lt;br&gt;
   The best solution to fix this is even though all shared components are &lt;br&gt;
  in a shared folder, each component should have  it’s on module. So only &lt;br&gt;
  one module needs to be imported for that particular component. Or to &lt;br&gt;
  make things much simpler update to newer versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a framework provide you with new feature make utmost use of it, Instead of sticking to the old methods you are used to. The leaning process is beneficial for the developer.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
