<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ deji adesoga - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ deji adesoga - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:29:47 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/desoga/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Realtime Chat Application with Angular 20 and Supabase ]]>
                </title>
                <description>
                    <![CDATA[ Chat applications let you talk in real-time with your friends, family, or coworkers, and help you quickly, effectively, and efficiently transfer of information. When you’re building modern web applications, chat applications are now pretty much a req... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-realtime-chat-app-with-angular-20-and-supabase/</link>
                <guid isPermaLink="false">6850913c10d2d4fd5525e0d6</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ supabase ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ deji adesoga ]]>
                </dc:creator>
                <pubDate>Mon, 16 Jun 2025 21:48:44 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750094888966/7ac31fee-bd4d-4353-b8cb-911ac60b4516.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Chat applications let you talk in real-time with your friends, family, or coworkers, and help you quickly, effectively, and efficiently transfer of information. When you’re building modern web applications, chat applications are now pretty much a requirement to enable collaboration and enhanced the user experience.</p>
<p>In this tutorial, we will break down how to build a chat application using modern technologies like Angular and Supabase. Building this chat application will help you learn features such as Google OAuth 2.0 for authentication, Angular router for navigation, the <code>CanActivate</code> route guard for route protection, and how to call Supabase functions to create, fetch and delete chats.</p>
<p>On the backend, you will learn how to create database tables in Supabase. You’ll also learn about Supabase functions and Supabase triggers.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-table-of-contents">Table of Contents</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-installations-and-account-configuration">Installations and Account Configuration:</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-the-user-interface-of-the-angular-application">How to Create the User Interface of the Angular Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-a-new-supabase-project">How to Set Up a New Supabase Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-google-oauth-20-for-authentication-and-authorization">How to Set Up Google OAuth 2.0 for Authentication and Authorization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-the-router-of-the-angular-application">How to Configure the Router of the Angular Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-the-authentication-service">How to Set Up the Authentication Service</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-the-service-functions-for-login-and-sign-out-functionality">How to Create the Service Functions for Login and Sign Out Functionality</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-integrate-the-authentication-service-function-in-the-template">How to Integrate the Authentication Service Function in the Template</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-route-protection-in-angular">How to Create Route Protection in Angular</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-and-setup-the-users-table-in-supabase-using-the-sql-editor">How to Create and Setup the Users Table in Supabase using the SQL Editor</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-row-level-security-policies-in-supabase-with-the-sql-editor">How to Configure Row Level Security Policies in Supabase with the SQL Editor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-supabase-functions-in-supabase-with-the-sql-editor">How to Configure Supabase Functions in Supabase with the SQL Editor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-supabase-trigger-in-supabase-with-the-sql-editor">How to Configure Supabase Trigger in Supabase with the SQL Editor</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-and-setup-the-chat-table-in-supabase-using-the-user-interface">How to Create and Setup the Chat Table in Supabase using the User Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-and-setup-the-chat-table-policies-in-supabase">How to Create and Setup the Chat Table Policies in Supabase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-integrate-functionality-to-create-a-new-chat-message-in-the-angular-application">How to Integrate Functionality to Create a New Chat Message in the Angular Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-fetch-data-in-the-angular-application-from-supabase">How to Fetch Data in the Angular Application from Supabase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-data-in-the-angular-application">How to Delete Data in the Angular Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-logout-functionality-in-the-angular-application">How to Implement Logout Functionality in the Angular Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<ul>
<li><p>HTML</p>
</li>
<li><p>JavaScript</p>
</li>
<li><p>TypeScript</p>
</li>
</ul>
<h2 id="heading-installations-and-account-configuration"><strong>Installations and Account Configuration:</strong></h2>
<p>Before we begin, make sure you have the following installed and ready:</p>
<ul>
<li><p><strong>Node.js and npm:</strong> Angular requires Node. You can check to see if you have it (and what version you have) by running <code>node -v</code> in your terminal.</p>
</li>
<li><p><strong>Angular CLI:</strong> This is the command-line tool to scaffold and manage Angular projects. If you don’t have it, install it with <code>npm install -g @angular/cli</code>. Verify with <code>ng version</code>.</p>
</li>
<li><p><strong>A Supabase account:</strong> Supabase offers a free tier. Sign up on the <a target="_blank" href="http://supabase.com/">Supabase</a> website if you haven’t already.</p>
</li>
</ul>
<p>You can also watch the video version of this article below, or on my <a target="_blank" href="https://youtu.be/8SRhekaJ5iI?si=Vddj2ayZ0rF1R3W2">YouTube channel</a>:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/8SRhekaJ5iI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-create-the-user-interface-of-the-angular-application">How to Create the User Interface of the Angular Application</h2>
<p>To create the user interface of the application, we’ll use <a target="_blank" href="https://getbootstrap.com/docs/5.0/getting-started/introduction/">Bootstrap 5</a>. In the <code>index.html</code> file of the Angular application, you are going to paste the Bootstrap 5 CDN link as seen below:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>NgChat<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">base</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/x-icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"favicon.ico"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
    <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">app-root</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">app-root</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"</span>
    <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"</span>
    <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Above, you have two CDN links from Bootstrap 5. The first is the <code>&lt;link&gt;</code> tag within the head section, while the second is the <code>&lt;script&gt;</code> tag which is right below the <code>&lt;app-root&gt;&lt;/app-root&gt;</code> tag.</p>
<p>Now that you have the Bootstrap 5 CDN link setup within the project, the next step is to create two new components called <strong>chat</strong> and <strong>login</strong>, respectively, within a pages folder. You can do that using the command below:</p>
<pre><code class="lang-powershell">ng g c pages/chat<span class="hljs-literal">-component</span> &amp;&amp; ng g c pages/login<span class="hljs-literal">-component</span>
</code></pre>
<p>The <code>login-component.html</code> is going to contain the code below:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"login-block"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-google btn-block text-uppercase btn-outline"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/dz4tt9omp/image/upload/v1712537582/google-logo.png"</span>&gt;</span> Signup Using Google<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
</code></pre>
<p>While the <code>login-component.css</code> will contain the code below:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.login-block</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
  <span class="hljs-attribute">display</span>:flex;
  <span class="hljs-attribute">justify-content</span>:center;
  <span class="hljs-attribute">align-items</span>:center;
  <span class="hljs-attribute">height</span>:<span class="hljs-number">100vh</span>;
}

<span class="hljs-selector-class">.btn</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2px</span>;
  <span class="hljs-attribute">text-transform</span>: capitalize;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">15px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">19px</span>;
  <span class="hljs-attribute">cursor</span>: pointer
}


<span class="hljs-selector-class">.btn-google</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#545454</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ffffff</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">1px</span> <span class="hljs-number">2px</span> <span class="hljs-number">1px</span> <span class="hljs-number">#ddd</span>;
}
</code></pre>
<p>To see how the user interface looks, you can call the <code>&lt;app-login /&gt;</code> tag with the <code>app.component.html</code> file, since the route navigations have not yet been configured. The user interface should look like the screenshot below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746232060227/98f18b59-d433-486b-adbe-f28302e8d901.png" alt="Screenshot of a web page running on localhost at port 4200. The page displays a centered white background with a single button labeled &quot;SIGNUP USING GOOGLE&quot; that includes a Google logo icon. The button is slightly elevated with a shadow effect." class="image--center mx-auto" width="1920" height="951" loading="lazy"></p>
<h2 id="heading-how-to-set-up-a-new-supabase-project">How to Set Up a New Supabase Project</h2>
<p>To set up Supabase, you will need to create a new account on <a target="_blank" href="https://supabase.com/">Supabase.com</a> by using either a GitHub account, or the traditional email and password. Once you’ve done this, you will be presented with a form to create a new organization as you can see in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747178536860/972076bf-ae5e-4b33-b18c-011e1e63b3a0.png" alt="Supabase form to create a new organization with name, type, and plan fields." class="image--center mx-auto" width="1920" height="892" loading="lazy"></p>
<p>The organization will be created as fast as your internet speed. Once that is done, the next form you’ll see will allow you to create a new Supabase project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747180463389/a41cd54d-4514-4a8b-8230-a348723b0a2f.png" alt="Supabase interface for creating a new project, showing fields for organization, project name, database password, and region selection." class="image--center mx-auto" width="1910" height="890" loading="lazy"></p>
<p>As you can see from the image above, all you need to do to create a new project is to set a database password and select a region close to where you think most of your users will be. This will help reduce latency. With that you can now click on the create button to create a new project.</p>
<p>Once the project creation is complete, you will be navigated to the dashboard below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747180885966/b9b89775-36cb-49e8-a596-c5ae4bad75a7.png" alt="Supabase dashboard showing a new project with no tables and a task list in progress." class="image--center mx-auto" width="1920" height="891" loading="lazy"></p>
<p>With that, you have now set up your new Supabase project.</p>
<h2 id="heading-how-to-set-up-google-oauth-20-for-authentication-and-authorization">How to Set Up Google OAuth 2.0 for Authentication and Authorization</h2>
<p>To set up Google OAuth 2.0, you need to create an account on <a target="_blank" href="https://console.cloud.google.com">Google Cloud Console</a>. Once you create an account, you will be navigated to the dashboard, where you can create a new project by clicking on the select project button on the top left-hand side of the dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747353793461/b42cd8f9-5a6c-4579-be15-074f9bf90e13.png" alt="Google Cloud console welcome page showing a $300 free credit offer. A 'Select a project' button is highlighted near the top." class="image--center mx-auto" width="1912" height="932" loading="lazy"></p>
<p>Once you’ve selected the newly created project, you can now begin implementing Google OAuth 2.0 by following these steps:</p>
<ul>
<li><p>Click on the hamburger menu on the left-hand side of the dashboard and hover over <strong>APIs and services.</strong></p>
</li>
<li><p>Click on <strong>Credentials</strong>, on the Credentials page, select <strong>Create Credentials</strong> at the top menu of the dashboard. A dropdown menu will appear. Select <strong>Create OAuth client ID</strong>.</p>
</li>
<li><p>On the Client ID page, you’ll get a warning message that says “To create an OAuth client ID, you must first configure your consent screen.” Click on the <strong>Configure consent screen</strong> button.</p>
</li>
</ul>
<p>Next, you’ll be directed to the Branding page. Click on the getting Started button, and you’ll be presented with a form on the overview page as you can see below. Then just fill out the form:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747358499033/47c07eda-9b1e-45ce-ae0b-bb478178a0a2.png" alt="Google Cloud console showing the 'Create branding' page under the Google Auth Platform. The user is filling out app information, including app name and support email, as part of the project configuration steps." class="image--center mx-auto" width="1916" height="885" loading="lazy"></p>
<p>You can now create the OAuth Consent Screen by heading to the Clients tab on the left-side of the dashboard and filling out the details for your application type, the name of your OAuth 2.0 client, as well as the Authorized JavaScript origins.</p>
<p>For the Authorized JavaScript origins, you can enter the URL (<a target="_blank" href="http://localhost:4200">http://localhost:4200</a>), since that is the development URL for our Angular application. Then click on the create button. You may get a warning saying “Note: It may take five minutes to a few hours for settings to take effect.”</p>
<p>Once the configuration is complete, you will get a modal that contains a Client ID and a Client Secret, as you can see below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747361106624/6ba6ed98-469a-4154-9d47-6719d982176e.png" alt="A Google Cloud OAuth client creation dialog displays the Client ID, Client secret, creation date, status as enabled, and a warning about downloading credentials before June 2025." class="image--center mx-auto" width="1918" height="884" loading="lazy"></p>
<p>Make sure you copy the Client ID and Client secret, as you will use this in the Supabase dashboard.</p>
<p>To complete the authentication and authorization setup, head to the Supabase dashboard. Then navigate to the Authentication menu, which is located in the items on the left-side of the dashboard. On this part of the dashboard, you will select <strong>Sign In / Providers</strong>.</p>
<p>On the Sign In / Providers page, scroll down to the <strong>Auth Providers</strong>, then select and enable <strong>Google</strong>. This is where you will paste in the credentials of the Client ID and Client Secret created on the <strong>Google Cloud Console</strong>. Then click on the save button – and make sure you copy the Callback URL (for OAuth).</p>
<p>The final step in this process is to head back to the GCP dashboard, and under the Clients tab, click on the edit icon of the OAuth 2.0 Client IDs you created previously.</p>
<p>Under the Authorized redirect URIs, click on the Add URI button. An input box will appear. Paste in the link of the Callback URL (for OAuth) you grabbed in the Supabase dashboard and click save.</p>
<h2 id="heading-how-to-configure-the-router-of-the-angular-application">How to Configure the Router of the Angular Application</h2>
<p>Earlier in this tutorial, you created two components: Chat and Login. At this point, you need to setup the route configuration in the <code>app.routes.ts</code>. In this file, add the code below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> routes: Routes = [
  {
    path: <span class="hljs-string">'chat'</span>,
    loadComponent: <span class="hljs-function">() =&gt;</span>
      <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/chat/chat-component'</span>).then(<span class="hljs-function">(<span class="hljs-params">com</span>) =&gt;</span> com.ChatComponent),
  },
  {
    path: <span class="hljs-string">'login'</span>,
    loadComponent: <span class="hljs-function">() =&gt;</span>
      <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/login/login-component'</span>).then(<span class="hljs-function">(<span class="hljs-params">com</span>) =&gt;</span> com.LoginComponent),
  },
  {
    path: <span class="hljs-string">''</span>,
    loadComponent: <span class="hljs-function">() =&gt;</span>
      <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/login/login-component'</span>).then(<span class="hljs-function">(<span class="hljs-params">com</span>) =&gt;</span> com.LoginComponent),
  },
];
</code></pre>
<p>Above, you can see the two components now have their separate routes called <strong>chat</strong> and <strong>login</strong>, respectively. They can be accessed anywhere in the application.</p>
<h2 id="heading-how-to-set-up-the-authentication-service">How to Set Up the Authentication Service</h2>
<p>To setup the authentication service in the Angular application, use the following command:</p>
<pre><code class="lang-bash">ng g s services/auth-service
</code></pre>
<p>Next, you’ll generate the environments folders to setup the environment variables using the below command:</p>
<pre><code class="lang-bash">ng g environments
</code></pre>
<p>The final configuration you need to do from the terminal before you begin creating the function for the Angular authentication service is to install Supabase with the command below:</p>
<pre><code class="lang-bash">npm i @supabase/supabase-js
</code></pre>
<p>And with that, you now have Supabase installed in the project and you can begin integrating the functions in the service. Start from the <code>environment.development.ts</code> file<strong>.</strong> The current structure of this file should look this way by default:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> environment = {};
</code></pre>
<p>To configure this file, you need to head to the Supabase dashboard. Locate and select the settings menu on the left hand panel of the dashboard. Under the <strong>Configuration</strong> tab, click on Data API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747569518560/94ae00c7-4f62-4cc7-a0f9-250088754acb.png" alt="Screenshot of Supabase API settings, showing the project URL and API keys section with arrows pointing to the URL and keys, plus buttons to copy each credential." class="image--center mx-auto" width="1918" height="886" loading="lazy"></p>
<p>You can now grab both the Project URL and anon public key (the arrow is pointing to it in the image above). You can now head over to the <code>environment.development.ts</code> file and paste in the values of the copied link following the format below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> environment = {
  production: <span class="hljs-literal">false</span>,
  supabaseUrl: <span class="hljs-string">'https://zktqzszvllbxvjfzkhvk.supabase.co'</span>,
  supabaseKey:
    <span class="hljs-string">'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InprdHF6c3p2bGxieHZqZnpraHZrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDcyNTg3MDgsImV4cCI6MjA2MjgzNDcwOH0.qf3MA-La6se8QijzLFALKc_XdiISmzDk7AZw4-na0uA'</span>,
};
</code></pre>
<p>With the environment variables all in place, you can now create the functions for the authentication service.</p>
<p>In the <code>auth-service.ts</code> which you created previously, start by importing the Supabase package as well as the environments file as you can see below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { SupabaseClient, createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment.development'</span>;
</code></pre>
<p>Next, complete the injection of the Supabase <code>npm</code> package by injecting it into your constructor:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { SupabaseClient, createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment.development'</span>;

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AuthService {
  supabase!: SupabaseClient;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
      <span class="hljs-built_in">this</span>.supabase = createClient(
      environment.supabaseUrl,
      environment.supabaseKey
    );
  }
}
</code></pre>
<h3 id="heading-how-to-create-the-service-functions-for-login-and-sign-out-functionality">How to Create the Service Functions for Login and Sign Out Functionality</h3>
<p>The final step in setting up the <code>Auth</code>service is to create the functions which will later be called in the template. You are going to create four functions which you can see in the code below:</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">private</span> router = inject(Router);
  <span class="hljs-keyword">private</span> _ngZone = inject(NgZone);

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.supabase = createClient(
      environment.supabaseUrl,
      environment.supabaseKey
    );

    <span class="hljs-built_in">this</span>.supabase.auth.onAuthStateChange(<span class="hljs-function">(<span class="hljs-params">event, session</span>) =&gt;</span> {

      <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'session'</span>, <span class="hljs-built_in">JSON</span>.stringify(session?.user));

      <span class="hljs-keyword">if</span> (session?.user) {
        <span class="hljs-built_in">this</span>._ngZone.run(<span class="hljs-function">() =&gt;</span> {
          <span class="hljs-built_in">this</span>.router.navigate([<span class="hljs-string">'/chat'</span>]);
        });
      }
    });
  }

  get isLoggedIn(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">const</span> user = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'session'</span>) <span class="hljs-keyword">as</span> <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">return</span> user === <span class="hljs-string">'undefined'</span> ? <span class="hljs-literal">false</span> : <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">async</span> signInWithGoogle() {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.auth.signInWithOAuth({
      provider: <span class="hljs-string">'google'</span>,
    });
  }

  <span class="hljs-keyword">async</span> signOut() {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.auth.signOut();
  }
}
</code></pre>
<p>The first function created is within the constructor. This is the <code>onAuthStateChange</code> callback function which is derived from Supabase and allows us to listen to Auth changes. It accepts two parameters called <code>event</code> and <code>session</code>.</p>
<p>Here, two conditions were instantiated within the <code>onAuthStateChange</code> callback function. They say that when the <code>session?.user</code> exists, you proceed to set the value to the local storage, and then navigate the user to the dashboard using the Angular router (which has been imported and injected using the <code>inject()</code> function).</p>
<p>The second function, <code>isLoggedIn()</code>, is a getter function that returns a Boolean. It returns either true or false, depending on if it is able to retrieve the user session from <code>localStorage</code>. This function will be used in the authentication guard which you’ll create later.</p>
<p>The third function, <code>signInWithGoogle()</code>, allows the user log into the dashboard using the <code>signInWithOAuth()</code> method provided by Supabase. This allows the user to log into the dashboard using a Google Gmail account.</p>
<p>The final function, <code>signOut()</code>, allows users to logout of the dashboard by resetting the state of the user session to null.</p>
<p>With all these functions created, the final code base in the <code>auth-service.ts</code> should look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable, NgZone, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { SupabaseClient, createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment.development'</span>;
<span class="hljs-keyword">import</span> { Router } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AuthService {
  <span class="hljs-keyword">private</span> supabase!: SupabaseClient;

  <span class="hljs-keyword">private</span> router = inject(Router);
  <span class="hljs-keyword">private</span> _ngZone = inject(NgZone);
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.supabase = createClient(
      environment.supabaseUrl,
      environment.supabaseKey
    );

    <span class="hljs-built_in">this</span>.supabase.auth.onAuthStateChange(<span class="hljs-function">(<span class="hljs-params">event, session</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'event'</span>, event);
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'session'</span>, session);

      <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'session'</span>, <span class="hljs-built_in">JSON</span>.stringify(session?.user));

      <span class="hljs-keyword">if</span> (session?.user) {
        <span class="hljs-built_in">this</span>._ngZone.run(<span class="hljs-function">() =&gt;</span> {
          <span class="hljs-built_in">this</span>.router.navigate([<span class="hljs-string">'/chat'</span>]);
        });
      }
    });
  }

  get isLoggedIn(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">const</span> user = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'session'</span>) <span class="hljs-keyword">as</span> <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">return</span> user === <span class="hljs-string">'undefined'</span> ? <span class="hljs-literal">false</span> : <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">async</span> signInWithGoogle() {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.auth.signInWithOAuth({
      provider: <span class="hljs-string">'google'</span>,
    });
  }

  <span class="hljs-keyword">async</span> signOut() {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.auth.signOut();
  }
}
</code></pre>
<p>You can now utilize these functions anywhere in the Angular project as a form of state management.</p>
<h3 id="heading-how-to-integrate-the-authentication-service-function-in-the-template">How to Integrate the Authentication Service Function in the Template</h3>
<p>The first function we’ll use is the <code>signInWithGoogle()</code> function. We’ll use it in the <code>login-component.ts</code> file to allow users log into the application as you can see below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/auth-service'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-login'</span>,
  standalone: <span class="hljs-literal">true</span>,
  imports: [],
  templateUrl: <span class="hljs-string">'./login-component.html'</span>,
  styleUrl: <span class="hljs-string">'./login-component.css'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> LoginComponent {
  <span class="hljs-keyword">private</span> auth = inject(AuthService);

  <span class="hljs-keyword">async</span> handleAuth() {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.auth.signInWithGoogle();
  }
}
</code></pre>
<p>Above, you implemented three features:</p>
<ul>
<li><p>Importing <code>AuthService</code> into the <code>LoginComponent</code></p>
</li>
<li><p>Injecting <code>AuthService</code> using the Inject function into the <code>LoginComponent</code></p>
</li>
<li><p>Creating the <code>handleAuth()</code> function that allows you call the <code>signInWithGoogle()</code> from the <code>AuthService</code> file.</p>
</li>
</ul>
<p>Now you can head to the <code>login-component.html</code> file and call the <code>handleAuth(</code>) function as below within the <code>&lt;a&gt;</code> tag:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"login-block"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"handleAuth()"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-google btn-block text-uppercase btn-outline"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/dz4tt9omp/image/upload/v1712537582/google-logo.png"</span>&gt;</span> Signup Using Google<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
</code></pre>
<p>Before you test the implementation, you will need to set the URL configuration in the Supabase dashboard. The URL configuration allows the URLs that authentication providers permit to redirect and post authentication, including wildcards.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748363896805/0b8f2ed1-ba45-44b9-93b8-0f470cb5ff32.png" alt="Interface displaying authentication settings, including site URL configuration and allowed redirect URLs for a web application." class="image--center mx-auto" width="1920" height="886" loading="lazy"></p>
<p>As you can see in the above image, the two Redirect URLs provided are localhost, since we are still currently creating the app in our local machine.</p>
<p>With this, you can test the Google OAuth 2.0 configuration by typing the localhost URL (<a target="_blank" href="http://localhost:4200/">http://localhost:4200</a>) in the browser, clicking on the <strong>Signup Using Google</strong> button<strong>,</strong> and selecting a Gmail account you want to sign up/login with. Then you should get navigated to the Chat component.</p>
<h2 id="heading-how-to-create-route-protection-in-angular">How to Create Route Protection in Angular</h2>
<p>To create route protection in Angular, you can use an in-built mechanism called a <strong>Route Guard</strong>. The Route Guard is used to control access to certain parts of the Angular application using certain conditions before a route is activated or accessible to the user.</p>
<p>In our case, you will be generating the Route Guard as a function (which is the default in our current version of Angular (20), instead of as a class) using the command below:</p>
<pre><code class="lang-bash">ng generate guard auth-guard
</code></pre>
<p>You will then see this prompt that asks “Which type of guard would you like to create?”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748365560338/650c5bf7-8e1c-45cf-915b-c988c167416a.png" alt="650c5bf7-8e1c-45cf-915b-c988c167416a" class="image--center mx-auto" width="1872" height="379" loading="lazy"></p>
<p>Use the spacebar to select <code>CanActivate</code>, and then press the Enter key to generate the Guard. Two files will be generated: the <code>auth-guard.spec.ts</code> file (for testing), and the <code>auth-guard.ts</code> file. Within the <code>auth-guard.ts</code> file, you will see the boilerplate code below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CanActivateFn } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> authGuard: CanActivateFn = <span class="hljs-function">(<span class="hljs-params">route, state</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
};
</code></pre>
<p>You can start modifying the above template by importing the Angular Router, the <code>AuthService</code> file that you created earlier, as well as the Inject function:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CanActivateFn, Router } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./services/auth-service'</span>;
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
</code></pre>
<p>Next, use the <code>isLoggedIn</code> getter that you created earlier in the <code>AuthService</code> file (which returns a Boolean) to conditionally activate the Chat dashboard for the user based on their login status using the code below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CanActivateFn, Router } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./services/auth-service'</span>;
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> authGuard: CanActivateFn = <span class="hljs-function">(<span class="hljs-params">route, state</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (inject(AuthService).isLoggedIn === <span class="hljs-literal">false</span>) {
    inject(Router).navigate([<span class="hljs-string">'/login'</span>]);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
};
</code></pre>
<p>To complete the Guard integration, head over to the <code>app.routes.ts</code> file and import and inject the Authentication Guard as you can see below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">import</span> { authGuard } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth-guard'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> routes: Routes = [
  {
    path: <span class="hljs-string">'chat'</span>,
    canActivate: [authGuard],
    loadComponent: <span class="hljs-function">() =&gt;</span>
      <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/chat/chat-component'</span>).then(<span class="hljs-function">(<span class="hljs-params">com</span>) =&gt;</span> com.ChatComponent),
  },
  {
    path: <span class="hljs-string">'login'</span>,
    loadComponent: <span class="hljs-function">() =&gt;</span>
      <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/login/login-component'</span>).then(<span class="hljs-function">(<span class="hljs-params">com</span>) =&gt;</span> com.LoginComponent),
  },
  {
    path: <span class="hljs-string">''</span>,
    loadComponent: <span class="hljs-function">() =&gt;</span>
      <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/login/login-component'</span>).then(<span class="hljs-function">(<span class="hljs-params">com</span>) =&gt;</span> com.LoginComponent),
  },
];
</code></pre>
<p>With this, the route protection implementation is now complete and only authenticated users can view the dashboard.</p>
<h2 id="heading-how-to-create-and-setup-the-users-table-in-supabase-using-the-sql-editor">How to Create and Setup the Users Table in Supabase using the SQL Editor</h2>
<p>To create and setup the users table, use the schema below:</p>
<ul>
<li><p>id (uuid)</p>
</li>
<li><p>full_name (text)</p>
</li>
<li><p>avatar_url (text)</p>
</li>
</ul>
<p>You can use the <strong>SQL</strong> Editor in Supabase. The SQL Editor is the third item on the menu panel in the Supabase dashboard. Here you are going to type in the query below in the SQL Editor input field:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-built_in">public</span>.users (
   id <span class="hljs-type">uuid</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">references</span> auth.users <span class="hljs-keyword">on</span> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">cascade</span>,
   full_name <span class="hljs-type">text</span> <span class="hljs-keyword">NULL</span>,
   avatar_url <span class="hljs-type">text</span> <span class="hljs-keyword">NULL</span>,
   <span class="hljs-keyword">primary key</span> (id)
);
</code></pre>
<p>You can now click on the Run button on the bottom right. You should get a message that says: <strong>Success. No rows returned</strong>, as you can see in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748394167618/5db26c97-a947-4233-8232-3aba72187a12.png" alt="SQL code for creating a user profile table with fields for id, full name, and avatar URL. Returns No rows returned after execution." class="image--center mx-auto" width="1918" height="885" loading="lazy"></p>
<p>Now let’s go ahead and enable row level security, as well as the Supabase function and trigger.</p>
<h3 id="heading-how-to-configure-row-level-security-policies-in-supabase-with-the-sql-editor">How to Configure Row Level Security Policies in Supabase with the SQL Editor</h3>
<p>Row Level Security (RLS) in Supabase allows you to control access to individual rows in your database tables based on custom logic. It’s one of the core features for building secure, multi-user applications with Supabase.</p>
<p>RLS lets you define SQL policies that determine which users can <code>SELECT</code>, <code>INSERT</code>, <code>UPDATE</code>, or <code>DELETE</code> specific rows in a table.</p>
<p>To enable RLS in the <strong>users</strong> table, type the command below in your SQL Editor:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-built_in">public</span>.users <span class="hljs-keyword">ENABLE</span> <span class="hljs-keyword">ROW</span> <span class="hljs-keyword">LEVEL</span> <span class="hljs-keyword">SECURITY</span>;
</code></pre>
<p>For the purpose of this tutorial, you are going to create just two policies, which are:</p>
<ol>
<li><p>The ability for users to access their own profile</p>
</li>
<li><p>The ability for users to update their own profile</p>
</li>
</ol>
<h4 id="heading-the-ability-for-users-to-access-their-own-profile">The ability for users to access their own profile</h4>
<p>To enable users access their own profile, head back to the SQL editor and create a new snippet with the following query:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">POLICY</span> "Permit Users to Access Their Profile"
  <span class="hljs-keyword">ON</span> <span class="hljs-built_in">public</span>.users
  <span class="hljs-keyword">FOR</span> <span class="hljs-keyword">SELECT</span>
  <span class="hljs-keyword">USING</span> ( auth.uid() = id );
</code></pre>
<p>With this query, users will be able to access their own profile as long as the authenticated user’s ID matches the <code>id</code> of the column of the row.</p>
<h4 id="heading-the-ability-for-users-to-update-their-own-profile">The ability for users to update their own profile</h4>
<p>To enable users update their own profile, head back to the SQL editor and create a new snippet with the following query:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">POLICY</span> "Permit Users to Update Their Profile"
  <span class="hljs-keyword">ON</span> <span class="hljs-built_in">public</span>.users
  <span class="hljs-keyword">FOR</span> <span class="hljs-keyword">UPDATE</span>
  <span class="hljs-keyword">USING</span> ( auth.uid() = id );
</code></pre>
<p>With the above query, users will be able to update their own profile as long as the authenticated user’s ID matches the <code>id</code> of the column of the row.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748397263186/11e886f4-0d08-4907-9859-9269ee0da2ef.png" alt="Screenshot of SQL Editor displaying a policy script for user profile updates, with navigation pane and no results returned." class="image--center mx-auto" width="1910" height="886" loading="lazy"></p>
<h3 id="heading-how-to-configure-supabase-functions-in-supabase-with-the-sql-editor">How to Configure Supabase Functions in Supabase with the SQL Editor</h3>
<p><strong>Supabase Functions</strong> are serverless functions that can be deployed and run within your Supabase project using <strong>Supabase Edge Functions</strong>.</p>
<p>In this project, you will create a trigger function that automatically creates a new row in the users table whenever a new user is created in the <code>auth.users</code> table.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span>
<span class="hljs-keyword">OR REPLACE</span> <span class="hljs-keyword">FUNCTION</span> <span class="hljs-built_in">public</span>.user_profile() <span class="hljs-keyword">RETURNS</span> <span class="hljs-type">TRIGGER</span> <span class="hljs-keyword">AS</span> $$<span class="pgsql"> <span class="hljs-keyword">BEGIN</span> <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-built_in">public</span>.users (id, full_name,avatar_url)
<span class="hljs-keyword">VALUES</span>
  (
    <span class="hljs-built_in">NEW</span>.id,
    <span class="hljs-built_in">NEW</span>.raw_user_meta_data -&gt;&gt; <span class="hljs-string">'full_name'</span>::<span class="hljs-type">TEXT</span>,
    <span class="hljs-built_in">NEW</span>.raw_user_meta_data -&gt;&gt; <span class="hljs-string">'avatar_url'</span>::<span class="hljs-type">TEXT</span>
  );
<span class="hljs-keyword">RETURN</span> <span class="hljs-built_in">NEW</span>;
<span class="hljs-keyword">END</span>;
$$</span> <span class="hljs-keyword">LANGUAGE</span> plpgsql <span class="hljs-keyword">SECURITY</span> <span class="hljs-keyword">DEFINER</span>;
</code></pre>
<p>To summarize the above query:</p>
<ul>
<li><p>You start by defining or replacing a function named <code>user_profile()</code> that will be used as a trigger.</p>
</li>
<li><p>Next, the trigger inserts a new row into the <code>public.users</code> table, and then extracts the <code>full_name</code> and <code>avatar_url</code> from the user's metadata as text.</p>
</li>
<li><p>The inserted record is now returned when the trigger function is complete</p>
</li>
<li><p>Finally, you use the <code>SECURITY DEFINER</code> keyword so that the function can run with the privileges of the user who created it.</p>
</li>
</ul>
<h3 id="heading-how-to-configure-supabase-trigger-in-supabase-with-the-sql-editor">How to Configure Supabase Trigger in Supabase with the SQL Editor</h3>
<p>A trigger in Supabase is a PostgreSQL feature used to automatically run a function in response to events on a table (SELECT, INSERT, UPDATE, or DELETE). It’s mostly used with Row Level Security or syncing data across tables.</p>
<p>In this project, you will create a Supabase trigger that automatically runs a function after a new user is created in the <code>auth.users</code> table.</p>
<pre><code class="lang-pgsql"> <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TRIGGER</span>
  create_user_trigger
  <span class="hljs-keyword">AFTER</span> <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">ON</span> auth.users
  <span class="hljs-keyword">FOR</span> <span class="hljs-keyword">EACH</span> <span class="hljs-keyword">ROW</span>
  <span class="hljs-keyword">EXECUTE</span> <span class="hljs-keyword">PROCEDURE</span>
    <span class="hljs-built_in">public</span>.user_profile();
</code></pre>
<p>To summarize the above query:</p>
<ul>
<li><p>The first line creates a <strong>trigger</strong> named <code>create_user_trigger</code>.</p>
</li>
<li><p>Next, the INSERT ON statement is activated when a user signs up and a new row is inserted into the <code>auth.users</code> table</p>
</li>
<li><p>Then the trigger runs once for every new user added in a new row.</p>
</li>
<li><p>Finally, the custom function <code>public.user_profile()</code> is called to perform some logic, typically inserting data into the <code>users</code> table.</p>
</li>
</ul>
<p>With the above integration, you can now log into the dashboard with a new google account and view the users table. There you will see the data that contains the <strong>id</strong>, <strong>full_name</strong>, and <strong>avatar_url</strong> as you can see below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748560146471/4c7663a8-6708-461a-8ed5-7ed8a3931318.png" alt="Screenshot of a database table editor displaying user data, including name and avatar URL, with options for filtering and sorting." class="image--center mx-auto" width="1920" height="878" loading="lazy"></p>
<h2 id="heading-how-to-create-and-setup-the-chat-table-in-supabase-using-the-user-interface">How to Create and Setup the Chat Table in Supabase using the User Interface</h2>
<p>To create the chat table, you will use the user interface in Supabase instead of the SQL Editor. To do this, you need to head to the Table Editor menu on the dashboard and click on the <strong>New Table</strong> button.</p>
<p>Once selected, a modal will popup which contains some input fields such as the table name, description, and columns. You can call the table name chat and omit the description for now since it’s optional. In the columns section, fill out the fields using the schema below:</p>
<ul>
<li><p>id (uuid)</p>
</li>
<li><p>Created At (date)</p>
</li>
<li><p>text (text)</p>
</li>
<li><p>editable (boolean)</p>
</li>
<li><p>sender (uuid)</p>
</li>
</ul>
<p>You can see the configuration for this in the table below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748564800333/0e879684-75d3-4c47-9f38-56d6041d6b38.png" alt="Screenshot of a table editor interface displaying fields for creating a new database table with various data types and options." class="image--center mx-auto" width="1882" height="879" loading="lazy"></p>
<p>Next up, you need to add a foreign key relation for the users table. To do this, you scroll to the bottom of the modal and click on the <strong>Add foreign key relation</strong> button. This will prompt another modal on top of the current modal. Here you can take the following steps:</p>
<ul>
<li><p>Under the <strong>Select a table to reference to</strong> label, select the <strong>users</strong> table<strong>.</strong></p>
</li>
<li><p>Under the <strong>public.chat</strong> label, select the <strong>sender</strong> option.</p>
</li>
<li><p>Under public.users label, select <strong>uuid.</strong></p>
</li>
<li><p>Under the <strong>Action if referenced row is updated</strong> label, select <strong>Cascade</strong>.</p>
</li>
<li><p>Under the <strong>Action if referenced row is removed</strong> label, select <strong>Cascade</strong> as well.</p>
</li>
</ul>
<p>If you’ve followed the above steps, you can now click on the save button, which successfully creates the chat table.</p>
<h2 id="heading-how-to-create-and-setup-the-chat-table-policies-in-supabase">How to Create and Setup the Chat Table Policies in Supabase</h2>
<p>The final step you need to perform for the chat table is to add a Row Level Security policy. You can do this by clicking the <strong>Add RLS policy</strong> button at the top of the chat table page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748567233239/6f69e305-5e09-4485-89b7-0115d41c8e0f.png" alt="A web interface displaying a Table Editor with options for managing chat and user data in a database schema." class="image--center mx-auto" width="1915" height="385" loading="lazy"></p>
<p>A new page will appear. Then you can click on the <strong>Create policy</strong> button, which displays a modal.</p>
<p>The first policy you will create is the <strong>DELETE</strong> policy, which will have the configuration you can see in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748779442105/f977dafb-ab73-4bb7-8643-9aa4e889c359.png" alt="Screenshot of a database policy settings interface for deleting user records based on user ID in a chat application." class="image--center mx-auto" width="1920" height="777" loading="lazy"></p>
<p>From the above image, we made these four implementations:</p>
<ul>
<li><p>First, we entered the policy name as “<strong>Delete by User ID</strong>“.</p>
</li>
<li><p>Next we selected the <strong>DELETE</strong> policy command clause.</p>
</li>
<li><p>Then under the targeted roles, we selected authenticated in the drop down select, to allow only authenticated users to perform delete operations.</p>
</li>
<li><p>Finally, under the <strong>USE OPTIONS ABOVE TO EDIT</strong> section, in line 7, we condition the query as <code>(auth.uid() = sender)</code> This allows only logged in users to delete their data.</p>
</li>
</ul>
<p>You can now click on the <strong>Save policy</strong> button to complete the DELETE setup.</p>
<p>The second policy you will create is the <strong>INSERT</strong> policy, which will have the configuration you can see in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748823531256/14aea41d-f221-42df-a739-b40a680395e3.png" alt="A policy configuration interface for inserting records in a chat table, targeting authenticated users with specific criteria." class="image--center mx-auto" width="1900" height="879" loading="lazy"></p>
<p>From the above image, four implementations were made:</p>
<ul>
<li><p>First, we entered the policy name as “<strong>Insert for Authenticated Users</strong>“.</p>
</li>
<li><p>Next we selected the <strong>INSERT</strong> policy command clause.</p>
</li>
<li><p>Then under the targeted roles, we selected authenticated in the drop down to allow only authenticated users perform insert operations.</p>
</li>
<li><p>Finally, under the <strong>USE OPTIONS ABOVE TO EDIT</strong> section, in line 7, the query was conditioned as <code>((sender = auth.uid()) AND (created_at = now()))</code>. The first condition ensures that the <code>sender</code> field in the inserted row matches the currently logged-in user's ID (from the Supabase JWT), while the second condition ensures that the <code>created_at</code> field is exactly equal to the current timestamp at the time of insertion.</p>
</li>
</ul>
<p>The third policy you will create is the <strong>SELECT</strong> policy, which will have the configuration you can see in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748824129598/8c15b701-dadb-4763-b5eb-e9484bd84470.png" alt="Row-level security policy configuration for a database table, specifying access permissions for authenticated users based on SELECT criteria." class="image--center mx-auto" width="1904" height="882" loading="lazy"></p>
<p>From the above image, we implemented four things:</p>
<ul>
<li><p>First, we entered the policy name as “<strong>Read Data for Authenticated Users</strong>“.</p>
</li>
<li><p>Next we selected the <strong>SELECT</strong> policy command clause, <em>pun intended</em> <strong>😊*</strong>.*</p>
</li>
<li><p>Then under the targeted roles, we selected authenticated in the drop down to allow only authenticated users perform select operations.</p>
</li>
<li><p>Finally, under the <strong>USE OPTIONS ABOVE TO EDIT</strong> section, in line 7, the query was conditioned as <code>true</code>. This allows all authenticated users to read all rows, or chats in our case.</p>
</li>
</ul>
<p>With the above implementation, you’ve created all the policies needed for the chat application.</p>
<h2 id="heading-how-to-integrate-functionality-to-create-a-new-chat-message-in-the-angular-application">How to Integrate Functionality to Create a New Chat Message in the Angular Application</h2>
<p>Now let’s add the code that lets users create a new chat message. First, start by creating a new Angular service using the command below:</p>
<pre><code class="lang-powershell">ng g s services/chat<span class="hljs-literal">-service</span>
</code></pre>
<p>Within the <code>chat-service.ts</code> file, you can now configure the Supabase client, just as we did in the <code>auth-service.ts</code> file as seen below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { SupabaseClient, createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment.development'</span>;

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ChatService {
  supabase!: SupabaseClient;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.supabase = createClient(
      environment.supabaseUrl,
      environment.supabaseKey
    );
  }
}
</code></pre>
<p>Next, create the function that enables you to create a new chat message. The function called <code>chatMessage()</code> is below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { SupabaseClient, createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment.development'</span>;

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ChatService {
  supabase!: SupabaseClient;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.supabase = createClient(
      environment.supabaseUrl,
      environment.supabaseKey
    );
  }

  <span class="hljs-keyword">async</span> chatMessage(text: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.from(<span class="hljs-string">'chat'</span>).insert({ text });

      <span class="hljs-keyword">if</span> (error) {
        alert(error.message);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      alert(error);
    }
  }
}
</code></pre>
<p>The above <code>chatMessage</code> function sends a chat message by inserting it into the <code>chat</code> table in Supabase.</p>
<p>You can now call this service in the <code>chat-component.ts</code> file. Within the <code>chat-component.ts</code>, import and inject the <code>chat-service.ts</code> file.</p>
<p>To send the data to the Supabase database, you need to setup Reactive form. Reactive form in Angular enables you to get data from an input field, which can be passed as a payload and then inserted into the database.</p>
<p>To setup a Reactive form in Angular, follow these steps:</p>
<ul>
<li><p>Import <code>FormBuilder</code>, <code>FormGroup</code>, <code>ReactiveFormsModule</code>, and <code>Validators</code> from <code>@angular/forms</code></p>
</li>
<li><p>Insert the <code>ReactiveFormsModule</code> inside of the imports array.</p>
</li>
<li><p>Inject the <code>FormBuilder</code> as a variable.</p>
</li>
<li><p>Declare a property that will hold the <strong>Reactive Form group.</strong></p>
</li>
<li><p>Inject the <code>FormBuilder</code> into the <code>ngOnInit</code> lifecycle hook.</p>
</li>
</ul>
<p>The code for the Reactive form setup is below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/auth-service'</span>;
<span class="hljs-keyword">import</span> {
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-chat'</span>,
  standalone: <span class="hljs-literal">true</span>,
  imports: [ReactiveFormsModule],
  templateUrl: <span class="hljs-string">'./chat-component.html'</span>,
  styleUrl: <span class="hljs-string">'./chat-component.css'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ChatComponent {
  chatForm!: FormGroup;
  <span class="hljs-keyword">private</span> fb = inject(FormBuilder);

  ngOnInit() {
    <span class="hljs-built_in">this</span>.chatForm = <span class="hljs-built_in">this</span>.fb.group({
      chat_message: [<span class="hljs-string">''</span>, Validators.required],
    });
  }
}
</code></pre>
<p>To complete the Reactive form setup, bind the <code>FormGroup</code> into the HTML file. Also bind the disabled attribute, which disables the button when the form is invalid, as you can see below:</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">form</span> [<span class="hljs-attr">formGroup</span>]=<span class="hljs-string">"chatForm"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-grow-0 py-3 px-4 border-top"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"input-group"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"chat_message"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type your message"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"!chatForm.valid"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
           <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>With the Reactive form setup complete, you can now create the function that calls the service which allows you create a new chat message.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/auth-service'</span>;
<span class="hljs-keyword">import</span> {
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;
<span class="hljs-keyword">import</span> { ChatService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/chat-service'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-chat'</span>,
  standalone: <span class="hljs-literal">true</span>,
  imports: [ReactiveFormsModule],
  templateUrl: <span class="hljs-string">'./chat-component.html'</span>,
  styleUrl: <span class="hljs-string">'./chat-component.css'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ChatComponent {
  <span class="hljs-keyword">private</span> chat_service = inject(ChatService);
  chatForm!: FormGroup;
  <span class="hljs-keyword">private</span> fb = inject(FormBuilder);

  ngOnInit() {
    <span class="hljs-built_in">this</span>.chatForm = <span class="hljs-built_in">this</span>.fb.group({
      chat_message: [<span class="hljs-string">''</span>, Validators.required],
    });
  }

  onSubmit() {
    <span class="hljs-keyword">const</span> formValue = <span class="hljs-built_in">this</span>.chatForm.value.chat_message;
    <span class="hljs-built_in">this</span>.chat_service
      .chatMessage(formValue)
      .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.chatForm.reset();
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
        alert(err.message);
      });
  }
}
</code></pre>
<p>The <code>onSubmit()</code> function in the above code basically does the following tasks:</p>
<ul>
<li><p>Gets the data from the Reactive form input field using the variable called <code>formValue</code></p>
</li>
<li><p>Calls the <code>chatMessage()</code> method from the <code>ChatService</code>, passing the data from the input field.</p>
</li>
<li><p>If successful, it resets the form.</p>
</li>
<li><p>If there's an error, it shows an alert with the error message.</p>
</li>
</ul>
<p>In the <code>chat-component.html</code> file, use of the <code>(ngSubmit)</code> directive to bind the <code>onSubmit()</code> function to the form:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> [<span class="hljs-attr">formGroup</span>]=<span class="hljs-string">"chatForm"</span> (<span class="hljs-attr">ngSubmit</span>)=<span class="hljs-string">"onSubmit()"</span>&gt;</span>
</code></pre>
<p>You can now test to see if the data we send from the input field saves directly into the <strong>chat</strong> database table.</p>
<p><strong>NOTE:</strong> make sure you <strong>delete all current users saved in the users table and authentication page on Supabase</strong> before trying this out for best results.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749042436895/a50416e7-3f8b-48a9-b8f3-96df520b2238.png" alt="Screenshot of a chat interface showing a message from &quot;Sharon Doe,&quot; with a timestamp and a text input field at the bottom." class="image--center mx-auto" width="1917" height="880" loading="lazy"></p>
<p>From the above image, you will click on the send button and send the <strong>Test</strong> data in the input field.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749043485066/94b53998-e924-44c2-bbfd-e26d591fdf54.png" alt="Table editor interface displaying the &quot;chat&quot; table with columns including ID, created_at, text, editable, and sender, showing entries and configuration options." class="image--center mx-auto" width="1911" height="739" loading="lazy"></p>
<p>The data should now be successfully saved into the database and the <strong>INSERT</strong> operation should now be integrated into the Angular application.</p>
<h2 id="heading-how-to-fetch-data-in-the-angular-application-from-supabase">How to Fetch Data in the Angular Application from Supabase</h2>
<p>To fetch data from the chat table from Supabase, start by creating a service function in the <code>chat-service.ts</code> file, as seen below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { SupabaseClient, createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment.development'</span>;

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ChatService {
  supabase!: SupabaseClient;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.supabase = createClient(
      environment.supabaseUrl,
      environment.supabaseKey
    );
  }

  <span class="hljs-keyword">async</span> chatMessage(text: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.from(<span class="hljs-string">'chat'</span>).insert({ text });
      <span class="hljs-keyword">if</span> (error) {
        alert(error.message);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      alert(error);
    }
  }

    <span class="hljs-keyword">async</span> listChat() {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase
        .from(<span class="hljs-string">'chat'</span>)
        .select(<span class="hljs-string">'*,users(*)'</span>);

      <span class="hljs-keyword">if</span> (error) {
        alert(error.message);
      }

      <span class="hljs-keyword">return</span> data;
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> error;
    }
  }
}
</code></pre>
<p>To summarize the function above called <code>listChat()</code>:</p>
<ul>
<li><p>We fetch the chat messages from the <code>chat</code> table using the <code>from</code> clause.</p>
</li>
<li><p>Then we include the related user info by joining the users table with <code>(select(', users()'))</code>.</p>
</li>
<li><p>An alert message is shown if there's a Supabase error.</p>
</li>
<li><p>Finally, the fetched data is returned, an error is thrown if something goes wrong.</p>
</li>
</ul>
<p>Before you head to the <code>chat-component.ts</code> file to consume the <code>listChat()</code> service function, you need to create an interface which helps shape the structure of the array of objects returned from Supabase. This gives us type safety and consistency.</p>
<p>To set up the interface, create an <strong>interface</strong> folder within the <strong>app</strong> directory. Here you will create a file called <code>chat-response.ts</code>. Then create the structure below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Ichat {
  created_at: <span class="hljs-built_in">string</span>;
  editable: <span class="hljs-built_in">boolean</span>;
  id: <span class="hljs-built_in">string</span>;
  sender: <span class="hljs-built_in">string</span>;
  text: <span class="hljs-built_in">string</span>;
  users: {
    avatar_url: <span class="hljs-built_in">string</span>;
    id: <span class="hljs-built_in">string</span>;
    full_name: <span class="hljs-built_in">string</span>;
  };
}
</code></pre>
<p>Heading back to the <code>chat-component.ts</code>, import both the interface which was named <code>Ichat</code> as well as <code>signal</code> and <code>effect</code> from <code>@angular/core</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, effect, inject, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/auth-service'</span>;
<span class="hljs-keyword">import</span> {
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;
<span class="hljs-keyword">import</span> { ChatService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/chat-service'</span>;
<span class="hljs-keyword">import</span> { Ichat } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../interface/chat-response'</span>;
</code></pre>
<p>Next, create a variable called <code>chats</code>, which will hold the response from the Supabase client as a signal:</p>
<pre><code class="lang-typescript">  chats = signal&lt;Ichat[]&gt;([]);
</code></pre>
<p>With this, you can now create the function that fetches the chat array of objects from the Supabase dashboard:</p>
<pre><code class="lang-typescript">  onListChat() {
    <span class="hljs-built_in">this</span>.chat_service
      .listChat()
      .then(<span class="hljs-function">(<span class="hljs-params">res: Ichat[] | <span class="hljs-literal">null</span></span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(res);
        <span class="hljs-keyword">if</span> (res !== <span class="hljs-literal">null</span>) {
          <span class="hljs-built_in">this</span>.chats.set(res);
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'No messages Found'</span>);
        }
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
        alert(err.message);
      });
  }
</code></pre>
<p>To summarize the function above, we started by:</p>
<ul>
<li><p>Calling the <code>listChat()</code> function from the <code>ChatService</code> to fetch the chat messages.</p>
</li>
<li><p>If messages are returned, it updates the chats signal with the result, by using the <code>set()</code> method derived from signals.</p>
</li>
<li><p>In the event where no messages are returned, it logs <code>"No messages Found"</code> to the console.</p>
</li>
<li><p>If an error occurs, it shows an alert with the error message.</p>
</li>
</ul>
<p>We then call the <code>onListChat()</code> function within the constructor using the <code>effect()</code> function, which helps handle asynchronous operations.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    effect(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">this</span>.onListChat();
    });
  }
</code></pre>
<p>When the application is saved, you can see the data in the console from the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749066359110/dedaa60a-c711-42d9-bac1-c9a130fcc4d1.png" alt="Screenshot of a chat application showing a message from Sharon Doe, along with developer tools displaying the message data in an array of object." class="image--center mx-auto" width="1912" height="868" loading="lazy"></p>
<p>You can now display the chat data in the HTML file of the page by getting rid of the placeholder text.</p>
<p>To do this, you can use the <code>@for</code> control flow in Angular as seen below:</p>
<pre><code class="lang-typescript">&lt;main&gt;
  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"container"</span>&gt;
    &lt;h3 <span class="hljs-keyword">class</span>=<span class="hljs-string">"mb-3"</span>&gt;Supa Chat &lt;button <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn btn-secondary"</span> style=<span class="hljs-string">"float: right;"</span>&gt;Log
        out&lt;/button&gt;
    &lt;/h3&gt;
    &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"card"</span>&gt;
      &lt;div&gt;

        &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"col-12 col-lg-12 col-xl-12"</span>&gt;
          <span class="hljs-meta">@for</span> (msg <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span>.chats(); track msg) {
          &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"position-relative"</span>&gt;
            &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"chat-messages p-4"</span>&gt;
              &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"chat-message-left pb-4"</span>&gt;
                &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"me-5"</span>&gt;
                  &lt;img src={{msg?.users?.avatar_url}} <span class="hljs-keyword">class</span>=<span class="hljs-string">"rounded-circle mr-1"</span> alt=<span class="hljs-string">"image"</span> width=<span class="hljs-string">"40"</span> height=<span class="hljs-string">"40"</span>&gt;
                  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"text-muted small text-nowrap mt-2"</span>&gt;{{msg?.created_at | date: <span class="hljs-string">'M/d/yy, h:mm a'</span>}}&lt;/div&gt;
                &lt;/div&gt;
                &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"flex-shrink-1 bg-light rounded py-2 px-3 ml-3"</span>&gt;
                  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"font-weight-bold mb-1"</span>&gt;{{msg?.users?.full_name}}&lt;/div&gt;
                  {{msg?.text}}
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          } <span class="hljs-meta">@empty</span> {
          &lt;div&gt;No chats available&lt;/div&gt;
          }

          &lt;form [formGroup]=<span class="hljs-string">"chatForm"</span> (ngSubmit)=<span class="hljs-string">"onSubmit()"</span>&gt;
            &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"flex-grow-0 py-3 px-4 border-top"</span>&gt;
              &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"input-group"</span>&gt;
                &lt;input formControlName=<span class="hljs-string">"chat_message"</span> <span class="hljs-keyword">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"form-control"</span> placeholder=<span class="hljs-string">"Type your message"</span>&gt;
                &lt;button [disabled]=<span class="hljs-string">"!chatForm.valid"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;Send&lt;/button&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/main&gt;
</code></pre>
<p>From the code above, right above the <code>div</code> with the <code>position-relative</code> class, we declared the <code>@for (msg of this.chats(); track msg)</code> control flow, which does the following:</p>
<ul>
<li><p>Loops through the array returned by <code>this.chats()</code> which is the signal variable that was declared in the template.</p>
</li>
<li><p>Assigns each item in the array to the <code>msg</code> variable.</p>
</li>
<li><p>Tracks each item by identity <code>track msg</code> for DOM updates.</p>
</li>
</ul>
<p>Next, within the loop, you called the data in the appropriate HTML tag to display the image, the date the chat was created, the full name, and the chat message as well.</p>
<p>Finally, you created an <code>@empty</code> block which displays the message <code>No chats available</code> if there are no items in the array.</p>
<p>You should have the outcome below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749082870784/85184bf1-3cfe-4808-a149-64a6b925e097.png" alt="A chat interface displaying two messages from the user &quot;adedeji adesoga,&quot; dated June 4, 2025, with a text input box at the bottom." class="image--center mx-auto" width="1904" height="715" loading="lazy"></p>
<h2 id="heading-how-to-delete-data-in-the-angular-application">How to Delete Data in the Angular Application</h2>
<p>When creating the delete functionality, first you need to create a service function in the <code>chat-service.ts</code> file as seen below:</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">async</span> deleteChat(id: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.from(<span class="hljs-string">'chat'</span>).delete().eq(<span class="hljs-string">'id'</span>, id);
    <span class="hljs-keyword">return</span> data;
  }
</code></pre>
<p>All the above function does is find the specific id provided from the parameter, and return the result of the delete operation.</p>
<p>Next, track the selected chat that was clicked from the array of listed chats and then pass the data down to your service.</p>
<p>To do this, first create a function within the service called <code>selectedChats()</code> which helps receive the data from the template:</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">public</span> savedChat = signal({});

 selectedChats(msg: Ichat) {
    <span class="hljs-built_in">this</span>.savedChat.set(msg);
  }
</code></pre>
<p>Above, we created the variable called <code>savedChat</code>. It’s declared as a signal that helps receive the object of the chat that we want to delete using the <code>set()</code> method.</p>
<p>You can now head to the <code>chat-component.ts</code> file to create the function that passed the data down to the <code>selectedChats()</code> function.</p>
<p>You can see this function below:</p>
<pre><code class="lang-typescript"> openDropDown(msg: Ichat) {
    <span class="hljs-built_in">console</span>.log(msg);
    <span class="hljs-built_in">this</span>.chat_service.selectedChats(msg);
  }
</code></pre>
<p>As you can see from the function above, once you bind it to the HTML element, it will make sure that you get the object of the specific chat that was clicked.</p>
<p>In our <code>chat-component.html</code> file, create a menu drop down that will help achieve this result as seen below:</p>
<pre><code class="lang-typescript">&lt;main&gt;
  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"container"</span>&gt;
    &lt;h3 <span class="hljs-keyword">class</span>=<span class="hljs-string">"mb-3"</span>&gt;Supa Chat &lt;button <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn btn-secondary"</span> style=<span class="hljs-string">"float: right;"</span>&gt;Log
        out&lt;/button&gt;
    &lt;/h3&gt;
    &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"card"</span>&gt;
      &lt;div&gt;

        &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"col-12 col-lg-12 col-xl-12"</span>&gt;
          <span class="hljs-meta">@for</span> (msg <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span>.chats(); track msg) {
          &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"position-relative"</span>&gt;
            &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"chat-messages p-4"</span>&gt;
              &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"chat-message-left pb-4"</span>&gt;
                &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"me-5"</span>&gt;
                  &lt;img src={{msg?.users?.avatar_url}} <span class="hljs-keyword">class</span>=<span class="hljs-string">"rounded-circle mr-1"</span> alt=<span class="hljs-string">"image"</span> width=<span class="hljs-string">"40"</span> height=<span class="hljs-string">"40"</span>&gt;
                  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"text-muted small text-nowrap mt-2"</span>&gt;{{msg?.created_at | date: <span class="hljs-string">'M/d/yy, h:mm a'</span>}}&lt;/div&gt;
                &lt;/div&gt;
                &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"flex-shrink-1 bg-light rounded py-2 px-3 ml-3"</span>&gt;
                  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"font-weight-bold mb-1"</span>&gt;{{msg?.users?.full_name}}&lt;/div&gt;
                  {{msg?.text}}
                &lt;/div&gt;

                &lt;!-- Delete Modal Button Menu--&gt;
                &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"dropdown"</span>&gt;
                  &lt;span (click)=<span class="hljs-string">"openDropDown(msg)"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"mt-3 ms-5"</span> <span class="hljs-keyword">type</span>=<span class="hljs-string">"button"</span> id=<span class="hljs-string">"dropdownMenuButton1"</span>
                    data-bs-toggle=<span class="hljs-string">"dropdown"</span> aria-expanded=<span class="hljs-string">"false"</span>&gt;
                    ...
                  &lt;/span&gt;
                  &lt;ul <span class="hljs-keyword">class</span>=<span class="hljs-string">"dropdown-menu"</span> aria-labelledby=<span class="hljs-string">"dropdownMenuButton1"</span>&gt;
                    &lt;li&gt;
                      &lt;a <span class="hljs-keyword">class</span>=<span class="hljs-string">"dropdown-item"</span> href=<span class="hljs-string">"#"</span> data-bs-toggle=<span class="hljs-string">"modal"</span> data-bs-target=<span class="hljs-string">"#exampleModal"</span>&gt;Delete&lt;/a&gt;
                    &lt;/li&gt;
                  &lt;/ul&gt;
                &lt;/div&gt;


              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          } <span class="hljs-meta">@empty</span> {
          &lt;div&gt;No chats available&lt;/div&gt;
          }

          &lt;form [formGroup]=<span class="hljs-string">"chatForm"</span> (ngSubmit)=<span class="hljs-string">"onSubmit()"</span>&gt;
            &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"flex-grow-0 py-3 px-4 border-top"</span>&gt;
              &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"input-group"</span>&gt;
                &lt;input formControlName=<span class="hljs-string">"chat_message"</span> <span class="hljs-keyword">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"form-control"</span> placeholder=<span class="hljs-string">"Type your message"</span>&gt;
                &lt;button [disabled]=<span class="hljs-string">"!chatForm.valid"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;Send&lt;/button&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/main&gt;
</code></pre>
<p>From the above code, take note of the following: the comment with the text <code>&lt;!-- Delete Modal Button Menu--&gt;</code> is created within the <code>@for</code> control flow. This is essential because it allows the <code>openDropDown(msg)</code> to receive the right object as a parameter when the drop down menu is clicked. A quick look at the console will reveal this.</p>
<p>You can now create the delete modal component, which allows you to consume the delete service required for a chat to be deleted.</p>
<p>To create the delete component, use the command below:</p>
<pre><code class="lang-powershell">ng g component layout/modal<span class="hljs-literal">-component</span>
</code></pre>
<p>The design for the delete component is a Bootstrap 5 modal that looks like this:</p>
<pre><code class="lang-typescript">&lt;!-- Modal --&gt;
&lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal fade"</span> id=<span class="hljs-string">"exampleModal"</span> tabindex=<span class="hljs-string">"-1"</span> aria-labelledby=<span class="hljs-string">"exampleModalLabel"</span> aria-hidden=<span class="hljs-string">"true"</span>&gt;
  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal-dialog"</span>&gt;
    &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal-content"</span>&gt;
      &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal-header"</span>&gt;
        &lt;h5 <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal-title"</span> id=<span class="hljs-string">"exampleModalLabel"</span>&gt;Modal title&lt;/h5&gt;
        &lt;button <span class="hljs-keyword">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn-close"</span> data-bs-dismiss=<span class="hljs-string">"modal"</span> aria-label=<span class="hljs-string">"Close"</span>&gt;&lt;/button&gt;
      &lt;/div&gt;
      &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal-body"</span>&gt;
        Are really sure you want to <span class="hljs-keyword">delete</span> <span class="hljs-built_in">this</span> message?
      &lt;/div&gt;
      &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"modal-footer"</span>&gt;
        &lt;button <span class="hljs-keyword">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn btn-secondary"</span> data-bs-dismiss=<span class="hljs-string">"modal"</span>&gt;No&lt;/button&gt;
        &lt;button [attr.data-bs-dismiss]=<span class="hljs-string">"!this.dismiss() === true ? 'modal' : null"</span> (click)=<span class="hljs-string">"deleteChat()"</span> <span class="hljs-keyword">type</span>=<span class="hljs-string">"button"</span>
          <span class="hljs-keyword">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;Yes&lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>If you paste the above code directly in your code editor, you’re going to get a host of errors because we have not created the <code>deleteChat()</code> function as well as the <code>dismiss()</code> signal variable in the template file. Let’s go ahead and do that.</p>
<p>The first step in setting up the <code>modal-componet.ts</code> file component is to import the appropriate modules as seen below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, effect, inject, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { ChatService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../services/chat.service'</span>;
<span class="hljs-keyword">import</span> { Router } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
</code></pre>
<p>Next, inject the <code>chatservice</code>, <code>Angular router</code>, as well as the the <code>dismiss</code> variable which is a signal as seen below:</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">private</span> chat_service = inject(ChatService);
  <span class="hljs-keyword">private</span> router = inject(Router);
  dismiss = signal(<span class="hljs-literal">false</span>);
</code></pre>
<p>With this you can now create the <code>deleteChat()</code> function as seen below:</p>
<pre><code class="lang-typescript">deleteChat() {
    <span class="hljs-keyword">const</span> id = (<span class="hljs-built_in">this</span>.chat_service.savedChat() <span class="hljs-keyword">as</span> { id: <span class="hljs-built_in">string</span> }).id;

    <span class="hljs-built_in">console</span>.log(id);

    <span class="hljs-built_in">this</span>.chat_service
      .deleteChat(id)
      .then(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">let</span> currentUrl = <span class="hljs-built_in">this</span>.router.url;

        <span class="hljs-built_in">this</span>.dismiss.set(<span class="hljs-literal">true</span>);

        <span class="hljs-built_in">this</span>.router
          .navigateByUrl(<span class="hljs-string">'/'</span>, { skipLocationChange: <span class="hljs-literal">true</span> })
          .then(<span class="hljs-function">() =&gt;</span> {
            <span class="hljs-built_in">this</span>.router.navigate([currentUrl]);
          });
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(err);
        alert(err.message);
      });
  }
</code></pre>
<ul>
<li><p>The first thing we did under the <code>deleteChat()</code> method was to extract the <code>id</code> from the chat service.</p>
</li>
<li><p>This <code>id</code> is then passed into the <code>deleteChat()</code> method from our service which helps delete the specific chat that was selected.</p>
</li>
<li><p>Once the chat has been deleted, the current route gets reloaded to update the UI.</p>
</li>
</ul>
<p>To activate the modal, you need to import the Modal Component in the <code>chat-component.html</code> file (last line of code below:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-3"</span>&gt;</span>Supa Chat <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-secondary"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"float: right;"</span>&gt;</span>Log
        out<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-12 col-lg-12 col-xl-12"</span>&gt;</span>
          @for (msg of this.chats(); track msg) {
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"position-relative"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"chat-messages p-4"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"chat-message-left pb-4"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"me-5"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{{msg?.users?.avatar_url}}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"rounded-circle mr-1"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"image"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"40"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"40"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-muted small text-nowrap mt-2"</span>&gt;</span>{{msg?.created_at | date: 'M/d/yy, h:mm a'}}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-shrink-1 bg-light rounded py-2 px-3 ml-3"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-weight-bold mb-1"</span>&gt;</span>{{msg?.users?.full_name}}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                  {{msg?.text}}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                <span class="hljs-comment">&lt;!-- Delete Modal Button Menu--&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"openDropDown(msg)"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-3 ms-5"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"dropdownMenuButton1"</span>
                    <span class="hljs-attr">data-bs-toggle</span>=<span class="hljs-string">"dropdown"</span> <span class="hljs-attr">aria-expanded</span>=<span class="hljs-string">"false"</span>&gt;</span>
                    ...
                  <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown-menu"</span> <span class="hljs-attr">aria-labelledby</span>=<span class="hljs-string">"dropdownMenuButton1"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown-item"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">data-bs-toggle</span>=<span class="hljs-string">"modal"</span> <span class="hljs-attr">data-bs-target</span>=<span class="hljs-string">"#exampleModal"</span>&gt;</span>Delete<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          } @empty {
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>No chats available<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          }

          <span class="hljs-tag">&lt;<span class="hljs-name">form</span> [<span class="hljs-attr">formGroup</span>]=<span class="hljs-string">"chatForm"</span> (<span class="hljs-attr">ngSubmit</span>)=<span class="hljs-string">"onSubmit()"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-grow-0 py-3 px-4 border-top"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"input-group"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"chat_message"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type your message"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"!chatForm.valid"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

<span class="hljs-comment">&lt;!-- modal --&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">app-modal</span> /&gt;</span>
</code></pre>
<p><strong>NOTE</strong>: Don’t forget to import the <strong>ModalComponent</strong> file in the <code>chat-component.ts</code> file to avoid having any errors.</p>
<p>You have now implemented the ability to Insert, read, and delete data. The final implementation is to integrate the logout functionality.</p>
<h2 id="heading-how-to-implement-logout-functionality-in-the-angular-application">How to Implement Logout Functionality in the Angular Application</h2>
<p>Earlier in the tutorial, within the <code>auth-service.ts</code> file, you created a function called <code>signOut()</code> as seen below:</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">async</span> signOut() {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.supabase.auth.signOut();
  }
</code></pre>
<p>In the <code>chat-component.ts</code> file, you will import and inject the <code>sigOut()</code> method. To do this, follow these steps:</p>
<ul>
<li><p>Import and inject the Angular router.</p>
</li>
<li><p>Import and inject the Authentication Service file</p>
</li>
<li><p>Create the <code>logOut()</code> function that consumes the <code>signOut()</code> service:</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> logOut() { 
<span class="hljs-built_in">this</span>.auth .signOut() .then(<span class="hljs-function">() =&gt;</span>
 { <span class="hljs-built_in">this</span>.router.navigate([<span class="hljs-string">'/login'</span>]); }) 
.catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
 alert(err.message);
 });
 }
</code></pre>
<ul>
<li>Finally in the <code>chat-component.html</code> file, within the button tag at the top of the page, call the <code>logout()</code> function using the <code>(click)</code> event handler:</li>
</ul>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-3"</span>&gt;</span>Supa Chat 
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"logOut()"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-secondary"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"float: right;"</span>&gt;</span>Log Out<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
</code></pre>
<p>Once the Log Out button is clicked, the user gets navigated to the Login page and the user state gets reset in the browser.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to build a real-time chat application using Angular and Supabase. We covered the following key concepts:</p>
<ul>
<li><p>How to create database tables in Supabase</p>
</li>
<li><p>How to create triggers and functions in Supabase</p>
</li>
<li><p>How to use signals to manage state in an Angular</p>
</li>
<li><p>How to create authentication and authorization using Supabase and Google OAuth 2.0</p>
</li>
<li><p>How to work with Reactive forms in Angular</p>
</li>
</ul>
<p>and lots more.</p>
<p>You can access the full codebase by cloning the repository on <a target="_blank" href="https://github.com/desoga10/ng-chat-20">GitHub</a>.</p>
<p>If you found this article helpful, consider subscribing to my <a target="_blank" href="https://www.youtube.com/@TheCodeAngle">YouTube channel</a> where I share hands-on tutorials on modern web development technologies like JavaScript, HTML, CSS, Angular, Supabase, Firebase, React, Third party API and AI tools, and many more. Cheers!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate Chart.js in Angular Using Data from a REST API ]]>
                </title>
                <description>
                    <![CDATA[ Charts are a great way of visually displaying large sets of data in formats that are easy to understand and analyze. They are a great way of showing the relationship that exists between two or more data sets. Different types of charts exist, some of ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-integrate-chart-js-in-angular-using-data-from-a-rest-api/</link>
                <guid isPermaLink="false">66d45e01f855545810e93415</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ chartjs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ deji adesoga ]]>
                </dc:creator>
                <pubDate>Thu, 30 Mar 2023 15:54:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/Copy-of-Copy-of-Orange-and-White-Vibrant-Food-YouTube-Thumbnail--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Charts are a great way of visually displaying large sets of data in formats that are easy to understand and analyze. They are a great way of showing the relationship that exists between two or more data sets.</p>
<p>Different types of charts exist, some of which includes bar chart, line chart, pie chart, radar chart, etc.</p>
<p>In this article, you will make use of a frontend framework called Angular as well as a JavaScript library called <a target="_blank" href="https://www.chartjs.org/">Chart.js</a> to display data from a cryptocurrency platform called <a target="_blank" href="https://coinranking.com/">Coinranking</a>. You will also make use of the Coinranking API to visualize a list of Cryptocurrencies along with their prices.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this tutorial, make sure you are familiar with the basics of the technologies listed below:</p>
<ul>
<li><p>HTML</p>
</li>
<li><p>JavaScript</p>
</li>
<li><p>TypeScript</p>
</li>
<li><p>npm</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-create-the-angular-application">How to Install and Create the Angular Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-integrate-chartjs-in-angular">How to Integrate Chart.js in Angular</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-integrate-the-rest-api">How to Integrate the REST API</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-display-the-data-in-the-chart">How to Display the Data in the Chart</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<p>You can also watch the video version of this article below, or on my <a target="_blank" href="https://www.youtube.com/thecodeangle">YouTube channel</a>:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/WCI4yvrzFwc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-install-and-create-the-angular-application">How to Install and Create the Angular Application</h2>
<p>Firstly, you need to install and set up Angular using the following steps:</p>
<h3 id="heading-step-1-install-npm-node-package-manager">Step 1: Install NPM (Node Package Manager)</h3>
<p>To install npm, you need to download Node.js. This can be done through the Node.js <a target="_blank" href="https://nodejs.org/en/download/">website</a>.</p>
<p>Node.js is an open-source cross platform server environment that can run on Windows, Linux, Unix, macOS, and more. It allows us to make use of npm to install libraries like Chart.js into our Angular application.</p>
<h3 id="heading-step-2-install-the-angular-cli-command-line-interface">Step 2: Install the Angular CLI (Command Line Interface)</h3>
<p>Once Node.js is installed, you can now download Angular into your machine with the terminal/command line using the command below:</p>
<pre><code class="lang-javascript">npm install -g @angular/cli
</code></pre>
<p>To confirm Angular has been installed, you can view the version by running the command <code>ng v</code>, which will give us the result below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Angular CLI Version</em></p>
<h3 id="heading-step-3-create-a-new-angular-project">Step 3: Create a New Angular Project</h3>
<p>Now that Angular has been installed, you can now create a new project by running the following commands in the terminal:</p>
<pre><code class="lang-javascript">ng <span class="hljs-keyword">new</span> ng-chart --routing=<span class="hljs-literal">false</span> --style=css
cd ng-chart
code .
</code></pre>
<p>With the commands above, we've created a new Angular project using the <code>ng new</code> command, disabled the routing and set the styling format to CSS.</p>
<p>Next, navigate into the project directory using the <code>cd</code> command, and open the project in Visual Studio Code.</p>
<p>You do not need to generate a new component for this project. You will use the two default files created by the Angular CLI — <code>app.component.ts</code> and <code>app.component.hmtl</code> — to render the chart. These files are in the <code>app</code> directory of your project.</p>
<p>The <code>app.component.html</code> file contains some boilerplate code which you need to get rid of. The Chart.js library can now be integrated into your application.</p>
<h2 id="heading-how-to-integrate-chartjs-in-angular">How to Integrate Chart.js in Angular</h2>
<p>To add the chart.js library to the Angular app, you need to run the following command inside your terminal:</p>
<pre><code class="lang-javascript">npm i chart.js
</code></pre>
<p>To confirm chart.js has been installed, you can check the <code>package.json</code> file in your project. You should see the chart.js version in the <code>dependencies</code> object shown in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Chart.js version</em></p>
<p>You can now import the chart.js library inside your project in the <code>app.component.ts</code> file as can be seen below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Chart <span class="hljs-keyword">from</span> <span class="hljs-string">'chart.js/auto'</span>;
</code></pre>
<p>Next, create a variable called <code>chart</code> and set it to an empty array:</p>
<pre><code class="lang-javascript">chart: any = []
</code></pre>
<p>Navigate to the getting started page of the chart.js <a target="_blank" href="https://www.chartjs.org/docs/latest/getting-started/">documentation</a> and grab the boilerplate code with static data, and paste it into the <code>ngOnInit</code> lifecycle hook:</p>
<p><strong>Note</strong>: The <code>ngOnInit</code> lifecycle hook in Angular gets triggered once after a component is initialized. That is, it gets called only when the first change detection occurs in an Angular component.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppComponent</span> </span>{
  title = <span class="hljs-string">'ng-chart'</span>;
  chart: any = [];

  <span class="hljs-keyword">constructor</span>() {}

  ngOnInit() {
    <span class="hljs-built_in">this</span>.chart = <span class="hljs-keyword">new</span> Chart(<span class="hljs-string">'canvas'</span>, {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'bar'</span>,
      <span class="hljs-attr">data</span>: {
        <span class="hljs-attr">labels</span>: [<span class="hljs-string">'Red'</span>, <span class="hljs-string">'Blue'</span>, <span class="hljs-string">'Yellow'</span>, <span class="hljs-string">'Green'</span>, <span class="hljs-string">'Purple'</span>, <span class="hljs-string">'Orange'</span>],
        <span class="hljs-attr">datasets</span>: [
          {
            <span class="hljs-attr">label</span>: <span class="hljs-string">'# of Votes'</span>,
            <span class="hljs-attr">data</span>: [<span class="hljs-number">12</span>, <span class="hljs-number">19</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>],
            <span class="hljs-attr">borderWidth</span>: <span class="hljs-number">1</span>,
          },
        ],
      },
      <span class="hljs-attr">options</span>: {
        <span class="hljs-attr">scales</span>: {
          <span class="hljs-attr">y</span>: {
            <span class="hljs-attr">beginAtZero</span>: <span class="hljs-literal">true</span>,
          },
        },
      },
    });
  }
}
</code></pre>
<p>In the code above, within the data object, there is a <code>labels</code> key which contains an array with different values. Beneath that you have the <code>datasets</code> array which contains an object.</p>
<p>Within the object, there is an array called <code>data</code> with values of different numbers. These values represent the data that will get displayed on the chart in the browser.</p>
<p>Before the chart gets displayed in the browser, you'll need to also grab the <code>&lt;canvas&gt;&lt;/canvas&gt;</code> html tag and paste it in the <code>app.component.html</code> file as seen below:</p>
<pre><code class="lang-javascript">&lt;div&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"canvas"</span>&gt;</span>{{chart}}<span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p><strong>Note</strong>: In the <code>app.component.html</code> file, the <code>&lt;canvas&gt;</code> tag has an <code>id</code> called <code>canvas</code>. This must have the same name as the value inside the parentheses before the <code>new Chart</code> object in the <code>app.component.ts</code> file. If the names are not the same, the chart will not display.</p>
<p>You can now compile and serve the project by running the <code>ng serve --open</code> command in the terminal. You should have the following results:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Displaying the charts with static data</em></p>
<h2 id="heading-how-to-integrate-the-rest-api">How to Integrate the REST API</h2>
<p>To integrate the REST API, head over to the Coinranking website using this <a target="_blank" href="https://developers.coinranking.com/api">link</a>. You should see a page like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Coinranking website</em></p>
<p>Start by clicking on the "Get API Key" button. You will be directed to a page where you can create an account and have access to an <strong>API</strong> key.</p>
<p>Copy the API key and open the <code>environment.ts</code> file in your Angular project. Within the object, create a variable called <code>API_KEY</code> and paste in the API key generated from CoinRanking as seen below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> environment = {
  <span class="hljs-attr">production</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">API_KEY</span>: <span class="hljs-string">'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'</span>,
};
</code></pre>
<p>Next, you need to copy the API to get all cryptocurrency coins from the CoinRanking <a target="_blank" href="https://developers.coinranking.com/api/documentation/coins">documentation</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Coinranking API documentation</em></p>
<p>To use the API link copied above, you need to create an Angular Service by running the command below:</p>
<pre><code class="lang-javascript">ng g service services/chart
</code></pre>
<p>With the <code>chart.service.ts</code> file created, you can now paste in the code that helps us consume the REST API as seen below:</p>
<p>To summarize the above code, here's what we did:</p>
<ul>
<li><p>We imported the <code>HttpClient</code>, <code>HttpHeaders</code> in <strong>line 2</strong>, as well as the <code>environment</code> file in <strong>line 3</strong>.</p>
</li>
<li><p>Between <strong>line 5</strong> and <strong>line 11</strong>, we created a variable called <code>httpOptions</code>. The <code>httpOptions</code> variable holds an object that contains the <code>HttpHeaders</code> configuration imported above. Here we set the <strong>content-type</strong>, passed the <code>API_KEY</code> variable from the <code>environment</code> file to the headers, and then set the <code>Access-Control-Allow-Origin</code> to a wildcard. This means the browser should allow request code from the origin.</p>
</li>
<li><p>In <strong>line 17</strong>, we created a private variable called <code>baseUrl</code> to hold the <strong>REST API</strong>, while in <strong>line 28</strong>, we created a variable called <code>proxyUrl</code> to hold the <strong>CORS Anywhere</strong> link. The <strong>CORS Anywhere</strong> link is a NodeJS proxy that adds CORS headers to the proxied request and helps to prevent CORS errors in the process.</p>
</li>
<li><p>In <strong>line 20</strong>, we injected the <code>HttpClient</code> into the constructor which makes it accessible within the Service.</p>
</li>
<li><p>Finally, we created a function called <code>cryptoData()</code> in <strong>line 22</strong>. Within this function lies a variable called <code>url</code>. We used the <code>url</code> variable to append both the <code>proxyUrl</code> and <code>baseUrl</code> variables to construct our API. Furthermore, in the <code>return</code> statement, we used the <code>get()</code> http method to fetch the data from the REST API.</p>
</li>
</ul>
<p>To make the <code>HttpClient</code> work, you need to import and inject the <code>HttpClientModule</code> into the <code>app.module.ts</code> file which can be seen below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { NgModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { BrowserModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/platform-browser'</span>;
<span class="hljs-keyword">import</span> { HttpClientModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;

<span class="hljs-keyword">import</span> { AppComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.component'</span>;

@NgModule({
  <span class="hljs-attr">declarations</span>: [AppComponent],
  <span class="hljs-attr">imports</span>: [BrowserModule, HttpClientModule],
  <span class="hljs-attr">providers</span>: [],
  <span class="hljs-attr">bootstrap</span>: [AppComponent],
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppModule</span> </span>{}
</code></pre>
<p>As seen above, the <code>HttpClientModule</code> was imported and injected into the <code>imports</code> array.</p>
<h2 id="heading-how-to-display-the-data-in-the-chart">How to Display the Data in the Chart</h2>
<p>To display the data on the chart, you need to head to the <code>app.component.ts</code> file and bring in your Chart service file as seen below:</p>
<ul>
<li><p>As seen above, we begin by importing the Chart Service and injecting it into our component in <strong>line 3</strong> and <strong>line 17</strong> respectively.</p>
</li>
<li><p>We created three variables called <code>result</code>, <code>coinPrice</code>, and <code>coinName</code>. These variables will be used later in the project to hold data.</p>
</li>
<li><p>Within the <code>ngOnInit()</code> lifecycle hook, we called the <code>cryptoData()</code> function in <code>line 20</code>, which returns an observable that gets subscribed to. This allows us to return a response from the data in the process.</p>
</li>
<li><p>In <strong>line 21</strong>, we called the <code>result</code> variable using the <code>this</code> keyword and set it to hold the data.</p>
</li>
<li><p>Next, in <strong>line 22</strong> and <strong>line 23</strong>, we called the <strong>coinPrice</strong> and <strong>coinName</strong> variables, mapped through the data, and attached the coin price and coin name to them respectively.</p>
</li>
<li><p>To see the results of the data in the browser, we used the <code>console.log()</code> function to display the data, as seen below:</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture10-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Data from the CoinRanking API displayed on the console.</em></p>
<p>The final thing to be done is to plot the data seen in the image above into chart.</p>
<ul>
<li><p>As seen above, we first replaced the static data in the labels in <strong>line 12</strong> with the coin name gotten from the CoinRanking API.</p>
</li>
<li><p>Next, we replaced the static data in <strong>line 15</strong> with the price gotten from the CoinRanking API.</p>
</li>
</ul>
<p>Now compile the project by running the <code>ng serve --open</code> command and see the results in the browser as seen below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/capture11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Final results of the chart</em></p>
<p><strong>Note</strong>: There is a possibility that you'll run into an error that says <strong>(Failed to load resource: the server responded with a status of 403 (Forbidden))</strong> after compiling the project.</p>
<p>What you need to do is to click on the CORS Anywhere link in the console which will open up in a new tab, with a button that says <strong>Request temporary access to the demo server.</strong> Click the button and then refresh the page. The data should now reflect on the chart.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to install and integrate the Chart.js library and a REST API in an Angular application. If you want access to the code base, you can clone the repo <a target="_blank" href="https://github.com/desoga10/ng-chart">here</a> on GitHub.</p>
<p>If you enjoyed this article, you can show your support by subscribing to my <a target="_blank" href="https://www.youtube.com/TheCodeAngle">YouTube channel</a> where I create awesome tutorials on web development technologies like JavaScript, React, Angular, Node.js, and more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Toggle an Element in React using React Hooks ]]>
                </title>
                <description>
                    <![CDATA[ When building a web application, toggling an element is one of the key features you are likely to come across and may need to implement in your project. There are various ways you can toggle an element. In this article, we will take a look at how we ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/toggle-elements-in-react-using-hooks/</link>
                <guid isPermaLink="false">66d45e043dce891ac3a967d0</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ deji adesoga ]]>
                </dc:creator>
                <pubDate>Mon, 07 Nov 2022 18:26:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/Copy-of-Coffee-Tutorial-YouTube-Thumbnail--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When building a web application, toggling an element is one of the key features you are likely to come across and may need to implement in your project.</p>
<p>There are various ways you can toggle an element. In this article, we will take a look at how we can implement toggle functionalities in five (5) different ways in React.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-setup-the-react-project">How to Install and Setup the React Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-toggle-an-element-using-logical-operators">How to Toggle an Element Using Logical Operators</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-toggle-an-element-using-the-usetoggle-hook">How to Toggle an Element Using the useToggle Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-toggle-an-element-using-the-ternary-operator">How to Toggle an Element Using the Ternary Operator</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-toggle-an-element-using-the-ifelse-statement">How to Toggle an Element Using the If/Else Statement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-toggle-an-element-using-css-conditional-styling">How to Toggle an Element Using CSS Conditional Styling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<p>You can also watch the video version of this article below, or on my <a target="_blank" href="https://www.youtube.com/watch?v=S_mgSHCWCmA&amp;t=15s">YouTube channel</a>:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5CTFTDpHHto" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-install-and-setup-the-react-project">How to Install and Setup the React Project</h2>
<p>To create a React project, you need to have access to NPM (Node Package Manager). Access to NPM requires that you have Node.js installed. You can install Node by heading to the <a target="_blank" href="https://nodejs.org/en/">official Node.js</a> website and downloading Node.js.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/npm-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Node.js official documentation</em></p>
<p>I advise selecting the "Recommended For Most Users" version. Once the installation is complete, you can open your terminal and run the commands <code>node -v</code> and <code>npm -v</code>. This gives you details on the version of Node and npm you have.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/terminal-2-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Terminal showing node and npm versions</em></p>
<p>Still in your terminal, you can now install <a target="_blank" href="https://create-react-app.dev/">Create React App</a> which is a platform that allows you to create a React project using the command below:</p>
<p><code>npm i create-react-app</code></p>
<p>The next step is to create a new React project from the terminal by running the command:</p>
<pre><code class="lang-php">npm init react-app toggle
cd toggle 
code .
</code></pre>
<p>Above, we created a new project called <code>toggle</code>. Then we navigated into the newly created project directory and opened the project in our code editor. We can now begin the process of implementing the different methods of toggling an element.</p>
<h2 id="heading-how-to-toggle-an-element-using-logical-operators">How to Toggle an Element Using Logical Operators</h2>
<p>To make sure the design of our page looks structured, we are going to set up Bootstrap 5 inside of the React project.</p>
<p>To do this, head to the <a target="_blank" href="https://getbootstrap.com/docs/5.0/getting-started/introduction/">Bootstrap 5</a> website and copy the CSS CDN link tag. Then go to your <code>index.html</code> file in your React project which can be found in the <code>public</code> directory. Paste the CDN link in the head section, you can see in the code below:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/favicon.ico"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"theme-color"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"#000000"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"Web site created using create-react-app"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"apple-touch-icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/logo192.png"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"manifest"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/manifest.json"</span> /&gt;</span>
  <span class="hljs-comment">&lt;!-- Bootstrap 5 CDN Link --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
    <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>React App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">noscript</span>&gt;</span>You need to enable JavaScript to run this app.<span class="hljs-tag">&lt;/<span class="hljs-name">noscript</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Next, create a new folder called <code>components</code> inside of the <code>src</code> directory. Then create a new file called <code>LogicalNot.js</code> inside the <code>components</code> folder. To implement the <strong>logical not</strong> operator method, we'll implement the code below:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> LogicalNot = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-comment">//Using Inline Function and the The Logical Not (!) to toggle state</span>
  <span class="hljs-keyword">const</span> [toggle, setToggle] = useState(<span class="hljs-literal">true</span>)

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setToggle(!toggle)} 
            class="btn btn-primary mb-5"&gt;
          Toggle State
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      {toggle &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>An item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A second item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A third item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A fourth item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>And a fifth one<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> LogicalNot
</code></pre>
<p>Inside of the <code>LogicalNot.js</code> file, we start off by:</p>
<ul>
<li><p>Importing the <code>useState</code> hook.</p>
</li>
<li><p>Then we create two variables called <code>toggle</code> and <code>setToggle</code>, while setting the initial state to <strong>true</strong>.</p>
</li>
<li><p>Next, inside of the <em>jsx</em> section, we create a button that has an <code>onClick</code> event handler. Within this <code>onClick</code> handler, we create an anonymous function by using the setter we declared earlier called <code>setToggle</code>. We then set the argument in the anonymous function to <code>!toggle</code> which creates a false effect when it's clicked.</p>
</li>
<li><p>Finally, we toggle the element in the <code>ul</code> tag by wrapping it around the <code>toggle</code> variable and then rendering it conditionally on the page using the logical <code>&amp;&amp;</code> Operator.</p>
</li>
</ul>
<p>To display the <code>LogicalNot.js</code> file on the browser, head to the <code>App.js</code> file and import the file there as seen below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> LogicalNot <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/LogicalNot'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App mt-5"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">LogicalNot</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>With that, you should have the result below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/logicanot_2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Logical not operator sample</em></p>
<h2 id="heading-how-to-toggle-an-element-using-the-usetoggle-hook">How to Toggle an Element Using the useToggle Hook</h2>
<p>You'll start this step by creating a new file called <code>ToggleHook.js</code> inside the <em>components</em> folder. Inside this file, import the <code>useState</code> hook.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
</code></pre>
<p>Next, create a variable called <code>useToggle</code> which will hold the logic for the <code>useToggle</code> hook as you can se below:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//Using useToggle Hook</span>

  <span class="hljs-keyword">const</span> useToggle = <span class="hljs-function">(<span class="hljs-params">initialState</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [toggleValue, setToggleValue] = useState(initialState);

    <span class="hljs-keyword">const</span> toggler = <span class="hljs-function">() =&gt;</span> { setToggleValue(!toggleValue) };
    <span class="hljs-keyword">return</span> [toggleValue, toggler]
  };
</code></pre>
<ul>
<li><p>Above, we created a callback function and then gave it a parameter called <code>initialState</code>.</p>
</li>
<li><p>Next, we used the <code>useState</code> hook to create a getter and a setter called <code>toggleValue</code> and <code>setToggleValue</code>, respectively. The <code>useState</code> hook takes the <code>initialState</code> parameter we created earlier which sets the initial value as false by default.</p>
</li>
<li><p>Finally we then created a variable called <code>toggler</code>. This variable holds an anonymous function that contains our <code>useState</code> variables and then sets the results to the opposite value when clicked. We then returned both the <code>toggleValue</code> and <code>toggler</code> variables in an array.</p>
</li>
</ul>
<p>With this we can now use the <code>useToggle</code> hook to create a getter and a setter variable as you can see below:</p>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> [toggle, setToggle] = useToggle();
</code></pre>
<p>We can now implement the logic of the <code>useToggle</code> hook in the <code>jsx</code> part of our code:</p>
<pre><code class="lang-html">    return (
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{setToggle}</span> 
            <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-secondary mb-5"</span>&gt;</span>
          Toggle State
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      {toggle &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>An item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A second item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A third item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A fourth item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>And a fifth one<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      )}

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  )
</code></pre>
<ul>
<li><p>Above, we created a button that contains an <code>onClick</code> event handler using the <code>setToggle</code> setter previously declared above.</p>
</li>
<li><p>Then we rendered the elements based on the boolean condition of the <code>toggle</code> variable when it gets clicked.</p>
</li>
</ul>
<p>With that, we should have the result below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/useToggle.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>useToggle sample</em></p>
<h2 id="heading-how-to-toggle-an-element-using-the-ternary-operator">How to Toggle an Element Using the Ternary Operator</h2>
<p>The ternary operator is a JavaScript operator that takes in three different operations, which are:</p>
<ul>
<li><p>A condition</p>
</li>
<li><p>A question mark (?) to execute a condition if true</p>
</li>
<li><p>A colon (:) to execute a condition if false</p>
</li>
</ul>
<p>To implement this method, you'll start by importing the <code>useState</code> hook:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
</code></pre>
<p>Then you need to create two variables using the <code>useState</code> hook and setting the default value to true:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [toggle, setToggle] = useState(<span class="hljs-literal">true</span>);
</code></pre>
<p>Next, create a variable called <code>handleClick</code> that holds a callback function. Within this function, call the <code>setToggle</code> setter and then pass in <code>!toggle</code> to return an opposite value when clicked, as you can see below:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    setToggle(!toggle);
  };
</code></pre>
<p>Finally, you can now render the logic of the variables you created in your <code>jsx</code>:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span> 
      <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-info mb-5"</span>&gt;</span>
      Toggle State
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      {toggle ?
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>An item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A second item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A third item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A fourth item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>And a fifth one<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        :
        <span class="hljs-tag">&lt;&gt;</span><span class="hljs-tag">&lt;/&gt;</span></span>
      }
    &lt;/div&gt;
  )
</code></pre>
<ul>
<li><p>Above we created a button that uses an <code>onClick</code> event handler to reference the <code>handleClick</code> variable we created earlier.</p>
</li>
<li><p>Then we can render the elements by using the <code>toogle</code> variable condition, as well as the question mark (?) which displays elements if the <code>toggle</code> variable is set to true, or displays an empty <em>jsx</em> fragment by using the colon (:) if the toggle variable is set to false.</p>
</li>
</ul>
<p>With that, we should have the result below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/ternary.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Ternary operator sample</em></p>
<h2 id="heading-how-to-toggle-an-element-using-the-ifelse-statement">How to Toggle an Element Using the If/Else Statement</h2>
<p>The <code>If/Else</code> statement is a conditional statement used to perform different actions based on certain parameters. The <code>if</code> statement executes a certain condition if it is true, and the <code>else</code> statement executes when the condition is false.</p>
<p>To see the if/else statement in action, let's begin by importing the <code>useState</code> hook:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
</code></pre>
<p>Next, create the getter and setter variables and then set the default value to true:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> [toggle, setToggle] = useState(<span class="hljs-literal">true</span>);
</code></pre>
<p>Next, create a variable called <code>handleClick</code> that holds the callback function. Within this function, call the <code>setToggle</code> setter and then pass in <code>!toggle</code> to return an opposite value when clicked, as you can see below:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    setToggle(!toggle)
  };
</code></pre>
<p>You can now display the elements by using the <code>toggle</code> getter in the <code>jsx</code> as you can see below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (toggle) {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-dark mb-5"</span>&gt;</span>Toggle State<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>An item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A second item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A third item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A fourth item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>And a fifth one<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-dark mb-5"</span>&gt;</span>Toggle State<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  }
</code></pre>
<ul>
<li><p>In the <code>jsx</code>, we wrapped the entire element around the <code>if/else</code> statement.</p>
</li>
<li><p>Within the <code>if</code> statement, we rendered the elements that contain the list items on the page when the <code>toggle</code> is set as true.</p>
</li>
<li><p>In the else block, however, when the toggle is set to false, only the button element gets returned.</p>
</li>
</ul>
<p>With that, we get the result below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/if-else.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>If/else statement sample</em></p>
<h2 id="heading-how-to-toggle-an-element-using-css-conditional-styling">How to Toggle an Element Using CSS Conditional Styling</h2>
<p>Conditional styling is one of the ways you can use to manipulate DOM elements in React based on a specific condition. As we've done previously, let's start by importing the <code>useState</code> hook in React:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
</code></pre>
<p>Next, set up your <code>useState</code> hook creating the required variables:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [toggle, setToggle] = useState(<span class="hljs-literal">true</span>);
</code></pre>
<p>Then create the function that helps set the value of your opposite state when clicked:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    setToggle(!toggle);
  };
</code></pre>
<p>With this you can now configure the conditional styling in the <code>jsx</code> section of your code:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-warning mb-5"</span>&gt;</span>Toggle State<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> <span class="hljs-attr">toggle</span> ? '<span class="hljs-attr">block</span>' <span class="hljs-attr">:</span> '<span class="hljs-attr">none</span>' }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>An item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A second item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A third item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>A fourth item<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-group-item"</span>&gt;</span>And a fifth one<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
</code></pre>
<ul>
<li><p>Above, we started by creating the button that contains the <code>onClick</code> event handler called <code>handleClick</code> as created earlier.</p>
</li>
<li><p>Then we used the style attribute in the <code>ul</code> tag to conditionally set the display to block when the <code>toggle</code> variable is true. If the <code>toggle</code> variable is false, we set the display to none. This is possible through the ternary operator.</p>
</li>
</ul>
<p>The result looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/condition.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Conditional styling sample</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned the various ways you can toggle elements in a React application. If you want access to the code base, you can clone the repo <a target="_blank" href="https://github.com/desoga10/showandhide">here</a> on GitHub.</p>
<p>Also, if you enjoyed this article, you can kindly show your support by subscribing to my <a target="_blank" href="https://www.youtube.com/TheCodeAngle">YouTube channel</a> where I create awesome tutorials on web development technologies like Angular, React, JavaScript, Html, CSS, and many more concepts.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate the Material UI Data Grid in React Using Data from a REST API ]]>
                </title>
                <description>
                    <![CDATA[ Material UI's Data Grid is a powerful and flexible data table. It makes it easy for you to display data and perform out of the box functionalities such as editing, sorting, filtering, pagination and more. In this article, we'll discuss why you should... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-integrate-material-ui-data-grid-in-react-using-data-from-a-rest-api/</link>
                <guid isPermaLink="false">66d45e037df3a1f32ee7f7f7</guid>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Datatables ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ deji adesoga ]]>
                </dc:creator>
                <pubDate>Thu, 06 Jan 2022 16:30:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/01/datagrid.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Material UI's Data Grid is a powerful and flexible data table. It makes it easy for you to display data and perform out of the box functionalities such as editing, sorting, filtering, pagination and more.</p>
<p>In this article, we'll discuss why you should use the <strong>Data Grid</strong> in <strong>Material UI</strong> in your project. And then we'll also go through how to install and set up the Data Grid, consume and integrate a RESTful API, and enable pagination as well as sorting and filtering.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-introduction-to-data-grid">Introduction to the Data Grid</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-use-the-material-ui-data-grid">Why use the Material UI Data Grid</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-setup-react-and-material-ui-data-grid">Installation and Setup of React and Material UI Data Grid</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-api-integration-and-consumption">API Integration and Consumption</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-display-the-api-results-in-the-material-ui-data-grid">Display API Results in Material UI Data Grid</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<p>Watch the video version of this article below, or on my <a target="_blank" href="https://www.youtube.com/watch?v=S_mgSHCWCmA&amp;t=15s">YouTube channel</a>:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/S_mgSHCWCmA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-introduction-to-data-grid">Introduction to Data Grid</h2>
<p>According to the Material UI documentation, <strong>Data Grid</strong> is a</p>
<blockquote>
<p>"<em>fast and extendable React data table and React data grid. It's a feature-rich component available in MIT or Commercial versions</em>".</p>
</blockquote>
<p>Basically, Data Grid in Material UI comes with some features like editing, sorting, filtering, updating, pagination, exports and so on by default.</p>
<p>The team also has future plans of implementing additional features like Excel export, Range selection, Group, Pivot, Aggregation.</p>
<p>For the purpose of this tutorial, we will be implementing some of the features of the Data Grid with a public REST API called <strong>JSONPlaceholder</strong></p>
<h2 id="heading-why-use-the-material-ui-data-grid">Why use the Material UI Data Grid</h2>
<p>There are some important reasons you might want to use the Material UI Data Grid:</p>
<ul>
<li><p>Accessibility</p>
</li>
<li><p>User Interaction</p>
</li>
<li><p>Data Presentation</p>
</li>
</ul>
<h4 id="heading-accessibility">Accessibility</h4>
<p>The Data Grid offers accessibility features such as cell highlighting. That is, every cell is accessible using the keyboard.</p>
<p>It also provides additional features such as keyboard navigation by using certain keys on the keyboard to change the focus of the table cells, along with density properties to determine the row and column height on the table.</p>
<h4 id="heading-user-interaction">User Interaction</h4>
<p>In terms of interaction, the Data Grid provides an inbuilt feature such as row selection by default. This allows the user to select certain rows on mouse click or using certain keyboard shortcuts.</p>
<p>The Data Grid in Material UI supports single and multiple row selection, ability to disable selection certain rows or all rows, checkbox selection and much more.</p>
<h4 id="heading-data-presentation">Data Presentation</h4>
<p>The Data Grid provides an inbuilt feature that allows data to be exported to CSV format.</p>
<p>Also, data can be manipulated by clicking a column header. This will trigger the sorting and filtering functionalities.</p>
<p>Another basic feature that comes by default is scrolling, which does not occur in a normal table by default.</p>
<h2 id="heading-how-to-install-and-setup-react-and-material-ui-data-grid">How to Install and Setup React and Material UI Data Grid</h2>
<p>To create a new project in React, you need to have <a target="_blank" href="https://nodejs.org/en/download/">Node.js</a> installed. This will give us access to npm in our terminal. We can then install and use Create React App using npm to create our project, by running the command below:</p>
<pre><code class="lang-javascript">npm i create-react-app
</code></pre>
<p>The next step is to create a new React project from the terminal by running the command below:</p>
<pre><code class="lang-javascript">npx create-react-app data-grid 
cd data-grid 
npm start
</code></pre>
<p>Above we created a new project called <code>data-grid</code>. Then we navigated into the newly created project directory and started the project with <em>npm.</em></p>
<p>By default, our project will be running on localhost:3000 in the browser.</p>
<p>Finally, we need to install two packages which are <strong>Material UI</strong> and the <strong>Data Grid</strong> using the command below:</p>
<pre><code class="lang-javascript">npm install @mui/x-data-grid @mui/material
</code></pre>
<h2 id="heading-api-integration-and-consumption">API Integration and Consumption</h2>
<p>To integrate our API, we need to create a new file and folder in our src directory that's created for us when we generated our project with Create-React-App. We will call this new folder <strong>Table</strong> and the file will be called <strong>DataGrid.js</strong>.</p>
<p>In the end, our folder structure should look something like this:</p>
<pre><code class="lang-javascript">&gt; src 
    &gt; Table 
        &gt; DataGrid.js 
.gitignore 
package-lock.json 
package.json 
README
</code></pre>
<p>In the DataGrid.js file, we will use a functional component. In this functional component, we will implement some of the following default features in React:</p>
<ul>
<li><p>useState hook</p>
</li>
<li><p>useEffect hook</p>
</li>
<li><p>The Fetch API</p>
</li>
</ul>
<h4 id="heading-the-usestate-hook">The useState Hook</h4>
<p>The <strong>useState</strong> hook in React is an inbuilt function that helps us track state in a functional component.</p>
<h4 id="heading-the-useeffect-hook">The useEffect Hook</h4>
<p>The <strong>useEffect</strong> hook allows us to handle side effects in our functional component. Some of these side effects could include things like updating the DOM, fetching data from a RESTful API, timer events, and so on.</p>
<h4 id="heading-the-fetch-api">The Fetch API</h4>
<p>The <strong>Fetch API</strong> in JavaScript allows web browsers to make HTTP requests to web servers. The request can be of any APIs that send and receive data in JSON or XML format.</p>
<p>Now that we've explored the concept of hooks and the Fetch API, let's generate a boilerplate functional component in our DataGrid.js file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> DataGrid= <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DataGrid
</code></pre>
<p>The next step is to consume the REST API from <a target="_blank" href="https://jsonplaceholder.typicode.com/posts">JSON placeholder</a>.</p>
<p>To do that, the first thing we need to do is to import the useState and useEffect hooks:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
</code></pre>
<p>Then we create a variable using the useState hook:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [tableData, setTableData] = useState([])
</code></pre>
<p>The <strong>tableData</strong> above serves as a getter, while the <strong>setTableData</strong> serves as a setter.</p>
<p>Finally, to access our data we will use the useEffect hook and the Fetch API:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
  fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>)
    .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> data.json())
    .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> setTableData(data))
}, [])
 <span class="hljs-built_in">console</span>.log(tableData)
</code></pre>
<p>Above, we can see that inside the useEffect hook, we did three things:</p>
<ul>
<li><p>First, inside the useEffect hook, we used Fetch to consume the JSON placeholder REST API</p>
</li>
<li><p>Then we converted the response we got into JSON format</p>
</li>
<li><p>Lastly, we passed the data from our response to the setter we created earlier called setTableData</p>
</li>
</ul>
<p>To be sure we got the right response, we logged the data we got into the console. To see the results in the console, we need to import our <strong>DataGrid.js</strong> inside our <strong>App.js</strong> file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> DataGrid <span class="hljs-keyword">from</span> <span class="hljs-string">'./Table/DataGrid'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DataGrid</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Then we get the result below, which consists of a list of 100 objects in an array:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/console.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>JSON Data in the Console</em></p>
<h2 id="heading-how-to-display-the-api-results-in-the-material-ui-data-grid">How to Display the API Results in the Material UI Data Grid</h2>
<p>To display our API results in the Material UI Data Grid, we need to import the Data Grid package into our DataGrid.js file:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { DataGrid } <span class="hljs-keyword">from</span> <span class="hljs-string">'@mui/x-data-grid'</span>
</code></pre>
<p>We then set up the configuration for the header section of our Data Grid table:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> columns = [
  { <span class="hljs-attr">field</span>: <span class="hljs-string">'id'</span>, <span class="hljs-attr">headerName</span>: <span class="hljs-string">'ID'</span> },
  { <span class="hljs-attr">field</span>: <span class="hljs-string">'title'</span>, <span class="hljs-attr">headerName</span>: <span class="hljs-string">'Title'</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">300</span> },
  { <span class="hljs-attr">field</span>: <span class="hljs-string">'body'</span>, <span class="hljs-attr">headerName</span>: <span class="hljs-string">'Body'</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">600</span> }
]
</code></pre>
<p>As you can see above, it is in an array of objects and it contains an <strong>id</strong>, <strong>title</strong> and a <strong>body,</strong> which is in accordance with the results we got from our REST API.</p>
<p>Finally, we bring in the DataGrid component into our return statement:</p>
<pre><code class="lang-jsx">&lt;div style={{ <span class="hljs-attr">height</span>: <span class="hljs-number">700</span>, <span class="hljs-attr">width</span>: <span class="hljs-string">'100%'</span> }}&gt;
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DataGrid</span>
       <span class="hljs-attr">rows</span>=<span class="hljs-string">{tableData}</span>
       <span class="hljs-attr">columns</span>=<span class="hljs-string">{columns}</span>
       <span class="hljs-attr">pageSize</span>=<span class="hljs-string">{12}</span>
     /&gt;</span></span>
   &lt;/div&gt;
</code></pre>
<p>Above, we have three properties inside the DataGrid component:</p>
<ul>
<li><p>The first one is the <strong>rows</strong> property. What we did with the row property was to pass in the results we got from our REST API, which is contained in the getter called tableData</p>
</li>
<li><p>The second property is called <strong>columns</strong>. This is the array of objects that contains the header of our DataGrid that include the id, title and body.</p>
</li>
<li><p>The last property is the pageSize. This helps us to set a limit to the amount of data that can be displayed at once. As you can see, we set this to 12 – the rest of the result is then paginated by default.</p>
</li>
</ul>
<p>In the end, our DataGrid.js file should look something like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { DataGrid } <span class="hljs-keyword">from</span> <span class="hljs-string">'@mui/x-data-grid'</span>

<span class="hljs-keyword">const</span> columns = [
  { <span class="hljs-attr">field</span>: <span class="hljs-string">'id'</span>, <span class="hljs-attr">headerName</span>: <span class="hljs-string">'ID'</span> },
  { <span class="hljs-attr">field</span>: <span class="hljs-string">'title'</span>, <span class="hljs-attr">headerName</span>: <span class="hljs-string">'Title'</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">300</span> },
  { <span class="hljs-attr">field</span>: <span class="hljs-string">'body'</span>, <span class="hljs-attr">headerName</span>: <span class="hljs-string">'Body'</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">600</span> }
]

<span class="hljs-keyword">const</span> DataGrid = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> [tableData, setTableData] = useState([])

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> data.json())
      .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> setTableData(data))

  }, [])

  <span class="hljs-built_in">console</span>.log(tableData)

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">height:</span> <span class="hljs-attr">700</span>, <span class="hljs-attr">width:</span> '<span class="hljs-attr">100</span>%' }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DataGrid</span>
        <span class="hljs-attr">rows</span>=<span class="hljs-string">{tableData}</span>
        <span class="hljs-attr">columns</span>=<span class="hljs-string">{columns}</span>
        <span class="hljs-attr">pageSize</span>=<span class="hljs-string">{12}</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DataGrid
</code></pre>
<p>The results in the browser should also look like the image we have below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/grid.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Data Grid Table Result</em></p>
<p>One awesome thing to note in the result of our image above is that, we have an out-of-the-box sorting and filtering functionality when we click on the header section(<em>id, title, body</em>) of our data table.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we learned about DataGrid in Material UI, React Hooks, REST API consumption and much more.</p>
<p>Also, the link to the code of this article can be found on <a target="_blank" href="https://github.com/desoga10/data-grid">GitHub</a>.</p>
<p>If you enjoyed this article, show your support by subscribing to my <a target="_blank" href="https://www.youtube.com/TheCodeAngle">YouTube channel</a> where I create awesome tutorials on web development technologies like JavaScript, React, Angular, Node.js, and more.</p>
<p>If you have any feedback or question on this post or other programming related questions, you can find me on Twitter <a target="_blank" href="https://twitter.com/thecodeangle">@thecodeangle</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
