<?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[ Ionic Framework - 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[ Ionic Framework - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 11 Jun 2026 16:39:51 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/ionic/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Create Native Apps with Ionic and Capacitor ]]>
                </title>
                <description>
                    <![CDATA[ Ionic and Capacitor are two powerful tools that can be used to build native mobile applications. Ionic is a UI framework that provides a wide range of components and features for building mobile apps, while Capacitor is a runtime that allows Ionic ap... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-native-apps-with-ionic-and-capacitor/</link>
                <guid isPermaLink="false">66b201d808bc664c3c097e75</guid>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 16 May 2023 21:14:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/ionic.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Ionic and Capacitor are two powerful tools that can be used to build native mobile applications. Ionic is a UI framework that provides a wide range of components and features for building mobile apps, while Capacitor is a runtime that allows Ionic apps to be deployed to both iOS and Android devices.</p>
<p>We just posted a course on the freeCodeCamp YouTube channel that will teach you everything you need to know to build native mobile apps with Ionic and Capacitor. You'll learn about the basics of Ionic, how to create your own components, and how to use Capacitor to deploy your apps to the App Store and Google Play.</p>
<p>By the end of this course, you'll be able to build native mobile apps that look and feel great on both iOS and Android devices. You'll also have the skills you need to build more complex and feature-rich apps.</p>
<p>Simon Grimm created this course. Simon is an Ionic Developer Expert and an experienced Ionic instructor.</p>
<p>In this course, you will learn:</p>
<ul>
<li>The basics of Ionic</li>
<li>How to create your own Ionic components</li>
<li>How to use Capacitor to deploy your apps to iOS and Android</li>
<li>How to use Ionic's built-in features, such as animations, gestures, and data storage</li>
<li>How to build more complex and feature-rich Ionic apps</li>
</ul>
<p>This course is for anyone who wants to learn how to build native mobile apps with Ionic and Capacitor. No prior experience with Ionic or Capacitor is required.</p>
<p>Simon will guide you through the process of building native apps for both iOS and Android, and deploying your Ionic app as a web app. You'll also discover how to build a desktop app with Electron, demonstrating the true cross-platform capabilities of Ionic and Capacitor.</p>
<p>Here are all the sections covered in this course:</p>
<ul>
<li>Getting started with Ionic &amp; Capacitor</li>
<li>Run and Debug your App</li>
<li>Building a Login Screen</li>
<li>Creating Introduction Slides with Swiper</li>
<li>Storing data with Capacitor Preferences</li>
<li>Responsive UI with Ionic Grid</li>
<li>Creating a Drawer Menu</li>
<li>Building a Tab Bar</li>
<li>Ionic Components and Modals</li>
<li>Ionic Animations API</li>
<li>Ionic Gesture API</li>
<li>Ionic Web Components and Styling</li>
<li>Using Capacitor Plugins</li>
<li>App Icon and Splash Screen</li>
<li>Building a native app for iOS and Android</li>
<li>Deploying Ionic as a Webapp</li>
<li>Building a Desktop app with Electron</li>
<li>Final Ionic React Cross Platform App</li>
<li>Where to learn more about Ionic?</li>
</ul>
<p>Watch the course full course on <a target="_blank" href="https://youtu.be/K7ghUiXLef8">the freeCodeCamp.org YouTube channel</a> (3-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/K7ghUiXLef8" 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>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I Created a Coronavirus Tracker App in Just 3 Days with Ionic and Firebase ]]>
                </title>
                <description>
                    <![CDATA[ By KAPIL RAGHUWANSHI I am really fond of Hybrid App technologies – they help us achieve so much in a single codebase. Using the Ionic Framework, I developed a cross-platform mobile solution for tracking Coronavirus cases in just 3 days.  In this tuto... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-corona-tracker-app-in-3-days/</link>
                <guid isPermaLink="false">66d4614a38f2dc3808b79105</guid>
                
                    <category>
                        <![CDATA[ Firebase ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 02 Jun 2020 20:31:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/CoronaSnap3-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By KAPIL RAGHUWANSHI</p>
<p>I am really fond of Hybrid App technologies – they help us achieve so much in a single codebase. Using the Ionic Framework, I developed a cross-platform mobile solution for tracking Coronavirus cases in just 3 days. </p>
<p>In this tutorial, we are going to learn how to develop an <strong>Android, iOS, and Progressive Web App</strong> to track the cases around us with the latest related news, help, and feedback sections. Brace yourself for a new coding journey! ?</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>The process of hybrid mobile app development is meant for all kinds of developers irrespective of their technology stack. Since we will be using three basic pillars of Web Development – <strong>HTML+CSS+JAVASCRIPT</strong> – at the core, you can easily understand the process and techniques. </p>
<p>Thus this tutorial is for everyone who has just a basic understanding of Web Fundamentals. So, let's begin.</p>
<h2 id="heading-day-0-idea-plan-and-engineering">Day 0 - Idea, Plan, and Engineering</h2>
<h3 id="heading-idea">Idea</h3>
<p>Initially, I was looking for the latest Covid19 cases around me (in March 2020). I got several links that had little difference in numbers. </p>
<p>Then, I realised that data from <a target="_blank" href="https://github.com/backtrackbaba/covid-api">https://github.com/backtrackbaba/covid-ap</a>i is regularly updated and more accurate. I decided to develop a universal, small, and handy mobile solution by using data provided by <strong>Johns Hopkins University.</strong></p>
<h3 id="heading-plan">Plan</h3>
<p>I planned to develop a cross-platform mobile solution that could be universally accessed by everyone. I considered the Ionic framework which would allow me to develop an <strong>Android</strong>, iOS &amp; Progressive Web App<strong> </strong>(PWA)<em>**</em>? by just writing and maintaining a single codebase. </p>
<p>I also wanted to show the COVID19 virus cases across the world and individual countries through various illustrations.</p>
<h3 id="heading-engineering">Engineering</h3>
<p>The idea was to develop 5 separate tabs which would be there at the bottom of the app:</p>
<ol>
<li><strong>World</strong> — would show the COVID19 Dashboard</li>
<li><strong>Country —</strong> would allow you to select a country to check the cases</li>
<li><strong>News —</strong> would get the latest news regarding the Coronavirus Pandemic</li>
<li><strong>Guidelines —</strong> would allow you to read and watch all advisories and guidelines</li>
<li><strong>Help</strong> — would provide help and feedback.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-170.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@sctgrhm?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Scott Graham / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<h3 id="heading-technology-stack">Technology Stack</h3>
<p>I have developed several websites and apps through Angular and Ionic before. But this time, I wanted to learn and use React.js. The below libraries are required to install using the Node package manager (<strong>npm</strong>):</p>
<ul>
<li><strong>React.js</strong> includes the latest react-hooks</li>
<li><strong>Ionic Framework</strong> (version 4) with <strong>Capacitor</strong></li>
<li><strong>Node.js</strong> environment to support JavaScript and npm libraries</li>
<li><strong>TypeScript</strong> language to write the actual code (.tsx files)</li>
<li><strong>Chart.js</strong> for various illustrations</li>
<li><strong>Firebase</strong> for hosting the content (<strong>Progressive Web App</strong>)</li>
</ul>
<h3 id="heading-tools">Tools</h3>
<ul>
<li>VS Code</li>
<li>Google Chrome</li>
<li>Android Studio for Android app</li>
<li>Xcode for iOS app (Unfortunately only available in Apple computers)</li>
</ul>
<h3 id="heading-installation-amp-scaffolding">Installation &amp; Scaffolding</h3>
<p>We need to install and configure all the above mentioned Software and Frameworks. So, let’s start with the first set of terminal commands (whether it's on Mac, Linux or Windows):</p>
<ol>
<li>Install ionic with global scope <strong>"npm install -g @ionic/cli native-run cordova-res"</strong></li>
<li>Create react app with Capacitor <strong>"ionic start corona-tracker tabs — type=react — capacitor"</strong></li>
<li>Add react hooks and pwa elements <strong>"npm install @ionic/react-hooks @ionic/pwa-elements"</strong></li>
</ol>
<p>Open the <strong>corona-tracker</strong> folder in your default workplace. You should have gotten all the default HTML, CSS and .tsx files with other sub-folders in the proper sequence. Now, go to your app folder and run these 2 commands</p>
<p> <strong>cd corona-tracker</strong>
 <strong>ionic serve</strong></p>
<p>Voilà! ?  Your Ionic app is now running in a web browser. Click on the localhost option in the terminal to check. ?This is your basic app installation and scaffolding. </p>
<p>So far, you should be running your ionic-react app in your local browser. Now <strong>index.html</strong> and <strong>index.tsx</strong> are your first pages for <strong>Single Page Applications (SPAs).</strong></p>
<h3 id="heading-app-routing">App Routing</h3>
<p>Let’s add routing to our app which will allow us to visit all 5 different tabs explained above. Open your <strong>App.tsx</strong> file and add the below router inside </p>
<pre><code class="lang-ts">     &lt;IonTabs&gt;
        &lt;IonRouterOutlet&gt;
          &lt;Route path=<span class="hljs-string">"/world"</span> component={WorldTab} exact={<span class="hljs-literal">true</span>} /&gt;
          &lt;Route path=<span class="hljs-string">"/country"</span> component={CountryTab} exact={<span class="hljs-literal">true</span>} /&gt;
          &lt;Route path=<span class="hljs-string">"/news"</span> component={NewsTab} /&gt;
          &lt;Route path=<span class="hljs-string">"/guidelines"</span> component={GuidelinesTab} /&gt;
          &lt;Route path=<span class="hljs-string">"/help"</span> component={HelpTab} /&gt;
          &lt;Route path=<span class="hljs-string">"/"</span> render={<span class="hljs-function">() =&gt;</span> &lt;Redirect to=<span class="hljs-string">"/world"</span> /&gt;} exact={<span class="hljs-literal">true</span>} /&gt;
        &lt;/IonRouterOutlet&gt;
        &lt;IonTabBar slot=<span class="hljs-string">"bottom"</span> &gt;
          &lt;IonTabButton tab=<span class="hljs-string">"WorldTab"</span> href=<span class="hljs-string">"/world"</span>&gt;
            &lt;IonIcon icon={planet} /&gt;
            &lt;IonLabel&gt;World&lt;/IonLabel&gt;
          &lt;/IonTabButton&gt;
          &lt;IonTabButton tab=<span class="hljs-string">"CountryTab"</span> href=<span class="hljs-string">"/country"</span>&gt;
            &lt;IonIcon icon={home} /&gt;
            &lt;IonLabel&gt; Country&lt;/IonLabel&gt;
          &lt;/IonTabButton&gt;
          &lt;IonTabButton tab=<span class="hljs-string">"NewsTab"</span> href=<span class="hljs-string">"/news"</span>&gt;
            &lt;IonIcon icon={newspaper} /&gt;
            &lt;IonLabel&gt; News&lt;/IonLabel&gt;
          &lt;/IonTabButton&gt;
          &lt;IonTabButton tab=<span class="hljs-string">"GuidelinesTab"</span> href=<span class="hljs-string">"/guidelines"</span>&gt;
            &lt;IonIcon icon={informationCircleOutline} /&gt;
            &lt;IonLabel&gt;Guidelines&lt;/IonLabel&gt;
          &lt;/IonTabButton&gt;
          &lt;IonTabButton tab=<span class="hljs-string">"HelpTab"</span> href=<span class="hljs-string">"/help"</span>&gt;
            &lt;IonIcon icon={call} /&gt;
            &lt;IonLabel&gt;Help&lt;/IonLabel&gt;
          &lt;/IonTabButton&gt;
        &lt;/IonTabBar&gt;
      &lt;/IonTabs&gt;
</code></pre>
<p>Check your app in the browser again, and you should see all these tabs with their respective pages. All tabs should be working smoothly with proper routing.</p>
<blockquote>
<p>_Let me know <em>in case you</em>'re <em>stuck with any issues related to installation, compile-time</em>, _or run-time errors.__</p>
</blockquote>
<p>This is it for <strong>Day</strong> 0.?</p>
<h2 id="heading-day-1-developing-covid19-dashboard-and-safety-guidelines-tabs">Day 1 - Developing COVID19 Dashboard and Safety Guidelines tabs</h2>
<p>In this part of the process, we will develop the <strong>World</strong> and <strong>Guidelines</strong> tabs for our Ionic React hybrid app. So far, we have done the basic installation and scaffolding of the app. We have also added 5 different tabs to our app with routing.</p>
<h3 id="heading-world-tab-design">World Tab: Design</h3>
<p>Let’s build our home page <strong>World</strong> tab now. I decided to have 4 different sections on this home tab:</p>
<ol>
<li>4 different boxes to show actual numbers: Total, Active, Recovered and Deaths</li>
<li>A Pie Chart depicting the number of cases</li>
<li>Slideshows for basic health tips</li>
<li>All countries listed with these categories in descending order.</li>
</ol>
<h3 id="heading-world-tab-data-amp-api">World Tab: Data &amp; API</h3>
<p>I have studied the open-source postman API source which contains all Application Programming Interfaces (APIs) related to Corona Cases <a target="_blank" href="https://documenter.getpostman.com/view/2568274/SzS8rjbe?version=latest"><strong>https://documenter.getpostman.com/view/2568274/SzS8rjbe?version=latest</strong></a><strong>.</strong> </p>
<p>First, we will consume the <a target="_blank" href="https://covidapi.info/api/v1/global">global</a> API with the Axios library to get the total global case count in the world using the useState &amp; useEffect React-hooks.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> [data, setData] = useState&lt;IGLobalCount&gt;();
<span class="hljs-keyword">const</span> [showLoading, setShowLoading] = useState(<span class="hljs-literal">true</span>);
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getGlobalData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-comment">//latest global count</span>
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> axios(<span class="hljs-string">'https://covidapi.info/api/v1/global'</span>);
      <span class="hljs-comment">// console.log(result);</span>
      setData(result.data);
      setShowLoading(<span class="hljs-literal">false</span>);
    };
    getGlobalData();
  }, []);
</code></pre>
<p>Then set the data inside your return block using HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">IonRow</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"casesBox"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">IonCol</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"totalCases"</span>&gt;</span>Total <span class="hljs-tag">&lt;<span class="hljs-name">AddNumFunc</span> <span class="hljs-attr">a</span>=<span class="hljs-string">{confirmed}</span> <span class="hljs-attr">b</span>=<span class="hljs-string">{recovered}</span> <span class="hljs-attr">c</span>=<span class="hljs-string">{deaths}</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">IonCol</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">IonCol</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"confirmedBox"</span>&gt;</span>Confirmed {confirmed?.toLocaleString()}<span class="hljs-tag">&lt;/<span class="hljs-name">IonCol</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">IonCol</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"recoveredBox"</span>&gt;</span>Recovered {recovered?.toLocaleString()}<span class="hljs-tag">&lt;/<span class="hljs-name">IonCol</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">IonCol</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"deathsBox"</span>&gt;</span>Deaths {deaths?.toLocaleString()}<span class="hljs-tag">&lt;/<span class="hljs-name">IonCol</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">IonRow</span>&gt;</span>
</code></pre>
<p>Now, we have the first 4 responsive boxes containing total cases, confirmed cases, recovered, and deaths. Install chart.js in your project using <strong>npm install react-chartjs-2</strong>. Let’s make use of the same data to draw a PieChart.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { Pie } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-chartjs-2'</span>;

&lt;IonCard <span class="hljs-keyword">class</span>=<span class="hljs-string">"pieCard"</span>&gt;
   &lt;Pie data={GlobalCasesPieChart}
     options={{
       legend: {
         display: <span class="hljs-literal">true</span>,
         position: <span class="hljs-string">'bottom'</span>,
       },
       plugins: {
         datalabels: {
           anchor: <span class="hljs-string">'end'</span>,
           clamp: <span class="hljs-string">'true'</span>,
           align: <span class="hljs-string">'bottom'</span>,
           color: <span class="hljs-string">'black'</span>,
           labels: {
             title: {
               font: {
                 weight: <span class="hljs-string">'bold'</span>
               }
             }
           }
         }
       }
    }} /&gt;
&lt;/IonCard&gt;
</code></pre>
<p>Now, we have 2 of the 4 sections in the <strong>World</strong> tab. So next, let’s add a slideshow depicting general health tips.</p>
<pre><code class="lang-ts">&lt;IonSlides <span class="hljs-keyword">class</span>=<span class="hljs-string">"tipsSlides"</span> options={slideOpts}&gt;
  &lt;IonSlide <span class="hljs-keyword">class</span>=<span class="hljs-string">"slide"</span>&gt;
    Maintain at least <span class="hljs-number">1</span> metre (<span class="hljs-number">3</span> feet) distance between yourself and anyone who is coughing or sneezing.
  &lt;/IonSlide&gt;
  &lt;IonSlide <span class="hljs-keyword">class</span>=<span class="hljs-string">"slide"</span>&gt;
    Regularly and thoroughly clean your hands <span class="hljs-keyword">with</span> an alcohol-based hand rub or wash them <span class="hljs-keyword">with</span> soap and water.
  &lt;/IonSlide&gt;
  &lt;IonSlide <span class="hljs-keyword">class</span>=<span class="hljs-string">"slide"</span>&gt;
    If you have fever, cough and difficulty breathing, seek medical care early.
  &lt;/IonSlide&gt;
  &lt;IonSlide <span class="hljs-keyword">class</span>=<span class="hljs-string">"slide"</span>&gt;
    Avoid touching eyes, nose and mouth. #StayHomeStaySafe
  &lt;/IonSlide&gt;
  &lt;IonSlide <span class="hljs-keyword">class</span>=<span class="hljs-string">"slide"</span>&gt;
    WHO Health Alert brings COVID<span class="hljs-number">-19</span> facts to billions via WhatsApp.
  &lt;/IonSlide&gt;
&lt;/IonSlides&gt;
</code></pre>
<p>Now, let’s make a data table for all countries in descending order to depict all kinds of cases. Again, we will consume the <a target="_blank" href="https://covidapi.info/api/v1/global/latest">latest</a> API with the Axios library to get the total global count for all the countries in the world using the useState &amp; useEffect React-hooks.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> [countryWiseData, setCountryWiseData] = useState&lt;ICountry[]&gt;([]);
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getGlobalCountryData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-comment">//latest global country wise count</span>
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> axios(<span class="hljs-string">'https://covidapi.info/api/v1/global/latest'</span>);
      <span class="hljs-comment">//console.log(result.data.result);</span>
      <span class="hljs-keyword">let</span> sortedResult = result.data.result;
      sortedResult.sort(<span class="hljs-function">(<span class="hljs-params">a: <span class="hljs-built_in">Object</span>, b: <span class="hljs-built_in">Object</span></span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> (<span class="hljs-built_in">Object</span>.values(a)[<span class="hljs-number">0</span>].confirmed &gt; <span class="hljs-built_in">Object</span>.values(b)[<span class="hljs-number">0</span>].confirmed ? <span class="hljs-number">-1</span> : (<span class="hljs-built_in">Object</span>.values(a)[<span class="hljs-number">0</span>].confirmed &lt; <span class="hljs-built_in">Object</span>.values(b)[<span class="hljs-number">0</span>].confirmed ? <span class="hljs-number">1</span> : <span class="hljs-number">0</span>));
      });
      setCountryWiseData(sortedResult);
    };
    getGlobalCountryData();
  }, []);
</code></pre>
<p>We have completed the development for our home tab with all 4 sections described above. You can see them below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/CoronaHybridAppSnap1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>World Tab — Working Emulator Snapshots in PWA, android and iOS</em></p>
<p>Now, let’s jump on to develop our next tab — the <strong>Guideline</strong>s <strong>Tab</strong>.</p>
<p>This is just an informative and static tab for various <strong>Advisor</strong>ies <strong>and Guidelines</strong> given by WHO and State Governments. We have added various images and videos here in the HTML:</p>
<pre><code class="lang-ts">&lt;IonList&gt;
   &lt;IonCard&gt;
     &lt;iframe title=<span class="hljs-string">"WHO"</span> width=<span class="hljs-string">"100%"</span> height=<span class="hljs-string">"200"</span> src=<span class="hljs-string">"https://www.youtube.com/embed/5jD2xd3Cv80"</span>
       allow=<span class="hljs-string">"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"</span>&gt;
     &lt;/iframe&gt;
   &lt;/IonCard&gt;
   &lt;IonCard&gt;
     &lt;IonCardHeader&gt;Symptoms&lt;/IonCardHeader&gt;
     &lt;IonImg <span class="hljs-keyword">class</span>=<span class="hljs-string">"guidlineImages"</span> src=<span class="hljs-string">"assets/images/Symptoms2.png"</span>&gt;&lt;/IonImg&gt;
   &lt;/IonCard&gt;
   &lt;IonCard&gt;
     &lt;IonCardHeader&gt;Diseases&lt;/IonCardHeader&gt;
     &lt;IonImg <span class="hljs-keyword">class</span>=<span class="hljs-string">"guidlineImages"</span> src=<span class="hljs-string">"assets/images/Symptoms.png"</span>&gt;&lt;/IonImg&gt;
   &lt;/IonCard&gt;
   &lt;IonCard&gt;
     &lt;IonCardHeader&gt;Myths Busted&lt;/IonCardHeader&gt;
     &lt;IonImg <span class="hljs-keyword">class</span>=<span class="hljs-string">"guidlineImages"</span> src=<span class="hljs-string">"assets/images/Myth.jpeg"</span>&gt;&lt;/IonImg&gt;
   &lt;/IonCard&gt;
   &lt;IonCard&gt;
     &lt;IonCardHeader&gt;Stress Distraction Tips&lt;/IonCardHeader&gt;
     &lt;IonImg <span class="hljs-keyword">class</span>=<span class="hljs-string">"guidlineImages"</span> src=<span class="hljs-string">"assets/images/Stress.jpg"</span>&gt;&lt;/IonImg&gt;
   &lt;/IonCard&gt;
   &lt;IonCard&gt;
     &lt;IonCardHeader&gt;Stay Home&lt;/IonCardHeader&gt;
     &lt;IonImg <span class="hljs-keyword">class</span>=<span class="hljs-string">"guidlineImages"</span> src=<span class="hljs-string">"assets/images/SafeHands.jpeg"</span>&gt;&lt;/IonImg&gt;
   &lt;/IonCard&gt;
&lt;/IonList&gt;
</code></pre>
<p>Let me know in case you get stuck with any issues related to installation, compile-time or run-time errors.</p>
<p>This is it for Day 1.?</p>
<h2 id="heading-day-2-developing-country-and-news-tabs">Day 2 - Developing Country and News tabs</h2>
<p>In this section we will develop <strong>Country</strong> and <strong>News</strong> tabs for our Ionic React hybrid app. So far, we have built <strong>World</strong> and <strong>Guideline</strong> tabs in our ionic react app with basic app routing.</p>
<h3 id="heading-country-tab-design">Country Tab: Design</h3>
<p>Let’s build our second page <strong>Country</strong> tab now. I decided to have 4 different sections on this second tab:</p>
<ol>
<li>Country Dropdown to select the country of your choice</li>
<li>4 different boxes to show actual numbers: Total, Active, Recovered and Deaths in the selected country</li>
<li>A Doughnut Chart depicting the number of cases in the selected country</li>
<li>Weekly Trend for the cases in the selected country. </li>
</ol>
<h3 id="heading-country-tab-data-amp-api">Country Tab: Data &amp; API</h3>
<p>I have studied the open-source postman link which contains all Application Programming Interfaces (APIs) related to Corona Cases <a target="_blank" href="https://documenter.getpostman.com/view/2568274/SzS8rjbe?version=latest"><strong>https://documenter.getpostman.com/view/2568274/SzS8rjbe?version=latest</strong></a><strong>.</strong> </p>
<p>Here, we will consume the <a target="_blank" href="https://covidapi.info/api/v1/country/">country</a> API with the Axios library to get the total count in the selected country using the useState &amp; useEffect React-hooks.</p>
<p>We will store the country the user has selected in local storage for other illustrations to update.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> moment <span class="hljs-keyword">from</span> <span class="hljs-string">'moment'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { Doughnut, Bar } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-chartjs-2'</span>;

  <span class="hljs-keyword">const</span> [yourCountry, setYourCountry] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">'IND'</span>);
  Storage.set({ key: <span class="hljs-string">'yourCountry'</span>, value: yourCountry });
  <span class="hljs-keyword">const</span> [countryData, setcountryData] = useState&lt;ICountryCount&gt;();
  <span class="hljs-keyword">const</span> [showLoading, setShowLoading] = useState(<span class="hljs-literal">true</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getCountryData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">let</span> result: <span class="hljs-built_in">any</span> = <span class="hljs-string">''</span>;
      <span class="hljs-keyword">const</span> { value } = <span class="hljs-keyword">await</span> Storage.get({ key: <span class="hljs-string">'yourCountry'</span> });
      <span class="hljs-keyword">if</span> (value) {
        result = <span class="hljs-keyword">await</span> axios(<span class="hljs-string">'https://covidapi.info/api/v1/country/'</span> + value + <span class="hljs-string">'/latest'</span>);
      } <span class="hljs-keyword">else</span> {
        result = <span class="hljs-keyword">await</span> axios(<span class="hljs-string">'https://covidapi.info/api/v1/country/'</span> + yourCountry + <span class="hljs-string">'/latest'</span>);
      }
      <span class="hljs-comment">// console.log(result);</span>
      setcountryData(result.data.result);
      setShowLoading(<span class="hljs-literal">false</span>);
    };

    getCountryData();
  }, [yourCountry]);
</code></pre>
<p>Now, consume the API to get the country-specific data:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> [countryTimeSeriesData, setcountryTimeSeriesData] = useState&lt;ISeriesCases[]&gt;([]);
  <span class="hljs-keyword">let</span> endDate: <span class="hljs-built_in">string</span> = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString().split(<span class="hljs-string">'T'</span>)[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">let</span> todaysDate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
  <span class="hljs-keyword">let</span> startDate: <span class="hljs-built_in">string</span> = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(todaysDate.getTime() - (<span class="hljs-number">5</span> * <span class="hljs-number">24</span> * <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>)).toISOString().split(<span class="hljs-string">'T'</span>)[<span class="hljs-number">0</span>];

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getCountryTimeSeriesData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> axios(<span class="hljs-string">'https://covidapi.info/api/v1/country/'</span> + yourCountry + <span class="hljs-string">'/timeseries/'</span> + startDate + <span class="hljs-string">'/'</span> + endDate);
      <span class="hljs-comment">// console.log(result);</span>
      setcountryTimeSeriesData(result.data.result);
      setShowLoading(<span class="hljs-literal">false</span>);
    };

    getCountryTimeSeriesData();
  }, [yourCountry, endDate, startDate]);
</code></pre>
<p>Now, design the Doughnut and Bar trend chart:</p>
<pre><code class="lang-ts">
 &lt;IonCard&gt;
    &lt;Doughnut
      data={CountryDoughnutChart}
      options={{
        legend: {
          display: <span class="hljs-literal">true</span>,
          position: <span class="hljs-string">'right'</span>
        },
        plugins: {
          datalabels: {
            anchor: <span class="hljs-string">'bottom'</span>,
            clamp: <span class="hljs-string">'true'</span>,
            align: <span class="hljs-string">'end'</span>,
            color: <span class="hljs-string">'black'</span>,
            labels: {
              title: {
                font: {
                  weight: <span class="hljs-string">'bold'</span>,
                  size: <span class="hljs-number">10</span>
                }
              }
            }
          }
        }
    }} /&gt;
  &lt;/IonCard&gt;
</code></pre>
<pre><code class="lang-ts"> &lt;Bar
   data={countryBarChart}
   options={{
     scales: {
       xAxes: [{
         stacked: <span class="hljs-literal">true</span>
       }],
       yAxes: [{
         stacked: <span class="hljs-literal">true</span>
       }]
     },
     title: {
       display: <span class="hljs-literal">true</span>,
       text: <span class="hljs-string">'Cases in the current week'</span>,
       fontSize: <span class="hljs-number">15</span>
     },
     legend: {
       display: <span class="hljs-literal">true</span>,
       position: <span class="hljs-string">'bottom'</span>
     },
     plugins: {
       datalabels: { display: <span class="hljs-literal">false</span> }
     }
   }}
  /&gt;
</code></pre>
<p>Now save the file and check it out in the browser. So, finally, we should get the below design:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/CoronaSnap3-2.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Country tab — Working Emulator Snapshots in PWA, android and iOS</em></p>
<p>Now, let’s keep going and develop our third tab — the <strong>News Tab.</strong></p>
<h3 id="heading-news-tab-design">News Tab: Design</h3>
<p>We have added a basic Ionic Card which contains various News resources such as URL, title, image, author and publisher’s details:</p>
<pre><code class="lang-ts">&lt;IonList&gt;
   {data.map(<span class="hljs-function">(<span class="hljs-params">news, idx</span>) =&gt;</span> (
     &lt;IonItem key={idx}&gt;
       &lt;IonCard&gt;
         &lt;IonImg src={news?.urlToImage} <span class="hljs-keyword">class</span>=<span class="hljs-string">"newsImage"</span> &gt;&lt;/IonImg&gt;
         &lt;IonGrid&gt;
           &lt;IonRow <span class="hljs-keyword">class</span>=<span class="hljs-string">"newsTitle"</span>&gt;{news?.title}&lt;/IonRow&gt;
           &lt;IonRow <span class="hljs-keyword">class</span>=<span class="hljs-string">"newsSource"</span>&gt;
             &lt;IonCol&gt;{news?.source?.name}&lt;/IonCol&gt;
             &lt;IonCol&gt;{trimSourceDetails(news?.author)}&lt;/IonCol&gt;
             {<span class="hljs-comment">/* &lt;IonCol text-right&gt;{moment(news?.publishedAt).format('DD MMM YYYY')}&lt;/IonCol&gt; */</span>}
           &lt;/IonRow&gt;
           &lt;IonRow <span class="hljs-keyword">class</span>=<span class="hljs-string">"newsContent"</span>&gt;{news?.description}&lt;/IonRow&gt;
         &lt;/IonGrid&gt;
       &lt;/IonCard&gt;
     &lt;/IonItem&gt;
   ))}
&lt;/IonList&gt;
</code></pre>
<h3 id="heading-news-tab-data-amp-api">News Tab: Data &amp; API</h3>
<p>To get the news, I used <strong>Newsapi.org</strong> which is <strong>not an open-source</strong> ?Application Programming Interface (API). But with a developer account, I searched news related to the Coronavirus. If you want to use other news APIs you can use them instead.</p>
<p>Here, we will consume the <a target="_blank" href="https://newsapi.org/v2/top-headlines">top-headlines</a> API with the Axios library to get the total count in the selected country using the useState &amp; useEffect React-hooks.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> [data, setData] = useState&lt;IArticles[]&gt;([]);
  <span class="hljs-keyword">const</span> [showLoading, setShowLoading] = useState(<span class="hljs-literal">true</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> getNewsData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> axios(<span class="hljs-string">'https://newsapi.org/v2/top-headlines?q=coronavirus&amp;language=en&amp;apiKey=YOUR_OWN_KEY'</span>);
      <span class="hljs-comment">// console.log(result);</span>
      setData(result.data.articles);
      setShowLoading(<span class="hljs-literal">false</span>);
    };

    getNewsData();
  }, []);
</code></pre>
<p>Now, save the file and check in the browser. So, finally, we should get the below design:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/CoronaSnap2.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>News tab — Working Emulator Snapshots in PWA, android and iOS</em></p>
<p>Let me know in case you get stuck with any issues related to codes, compile-time or run-time errors.</p>
<p>This is it for Day 2.?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-day-3-developing-the-help-tab-and-deployment">Day 3 - Developing the Help Tab and Deployment</h2>
<p>In this section - our last one - we will develop the <strong>Help tab</strong> and learn to use <strong>Capacitor to build</strong> A<strong>ndroid</strong> and <strong>iOS</strong> apps. </p>
<p>So far, we have built the <strong>World, Country, News</strong>, <strong>and Guideline</strong> tabs in our ionic react app. Also, will deploy our app to Firebase as a <strong>PWA.</strong> It is going to be most interesting now. Pull on your socks and be ready to actually see your own app in a real environment.</p>
<h3 id="heading-help-tab-design">Help Tab: Design</h3>
<p>First, let’s create the Help and Feedback tab. This is just an informative and static tab for help from the <strong>World Health Organization (WHO</strong>) that gives feedback to the developer.</p>
<pre><code class="lang-ts">&lt;IonCard&gt;
    &lt;IonList&gt;
      &lt;IonItem&gt;
        &lt;IonLabel&gt;Call WHO helpline <span class="hljs-built_in">Number</span>&lt;/IonLabel&gt;
        &lt;IonButton color=<span class="hljs-string">'warning'</span> href=<span class="hljs-string">"tel:+41-22-7912111"</span>&gt;&lt;IonIcon slot=<span class="hljs-string">"start"</span> icon={callOutline} /&gt; Call&lt;/IonButton&gt;
      &lt;/IonItem&gt;
      &lt;IonItem&gt;
        &lt;IonLabel&gt;Email WHO Team&lt;/IonLabel&gt;
        &lt;IonButton color=<span class="hljs-string">'warning'</span> href=<span class="hljs-string">"mailto:mediainquiries@who.int"</span>&gt;&lt;IonIcon slot=<span class="hljs-string">"start"</span> icon={mailOutline} /&gt; Email&lt;/IonButton&gt;
      &lt;/IonItem&gt;
      &lt;IonItem&gt;
        &lt;IonLabel&gt;Text <span class="hljs-string">'Hi'</span> to WHO helpdesk&lt;/IonLabel&gt;
        &lt;IonButton color=<span class="hljs-string">'warning'</span> href=<span class="hljs-string">"https://api.whatsapp.com/send?phone=41798931892&amp;text=hi&amp;source=&amp;data="</span>&gt;&lt;IonIcon slot=<span class="hljs-string">"start"</span> icon={logoWhatsapp} /&gt; WhatsApp&lt;/IonButton&gt;
      &lt;/IonItem&gt;
      &lt;IonItem&gt;
        &lt;IonLabel&gt;Donate via WHO website&lt;/IonLabel&gt;
        &lt;IonButton color=<span class="hljs-string">'warning'</span> href=<span class="hljs-string">"https://www.who.int/emergencies/diseases/novel-coronavirus-2019/donate"</span>&gt;&lt;IonIcon slot=<span class="hljs-string">"start"</span> icon={walletOutline} /&gt; Donate&lt;/IonButton&gt;
      &lt;/IonItem&gt;
    &lt;/IonList&gt;
  &lt;/IonCard&gt;
</code></pre>
<h2 id="heading-environment-installation-check">Environment Installation Check</h2>
<p>As mentioned in our first (Day 0) section, we should have all the below Software installed in our system:</p>
<ul>
<li>VS Code</li>
<li>Google Chrome</li>
<li>Android Studio for Android app</li>
<li>Xcode for iOS app (Unfortunately only available in Apple computers)</li>
</ul>
<p>We need to set the required path, and install the targeted Android (such as Android 9 Pie) and iOS (such as iOS 11) operating system versions. </p>
<p>Wait, don’t worry if you are very new to this platform setup. Follow the next steps sequentially with all the provided <strong>important</strong> <strong>links</strong> in the coming sections.</p>
<p>We have already installed <strong>Capacitor</strong> in our first terminal command while creating the ionic react app. (Check Day 0 for the installation section). Capacitor is the Native Bridge for Cross-Platform Web Apps. It invokes Native SDKs on iOS, Android, and the Web with one codebase.</p>
<p>// Go to your project directory and run below commands to initialize Capacitor into your project and add the Android and iOS platforms to your app:</p>
<p><strong>npm install --save @capacitor/core @capacitor/cli
npx cap init
npx add android
npx add ios</strong></p>
<h2 id="heading-app-icons-and-splash-screens">App icons and Splash screens</h2>
<p>For creating android and iOS icons and splash screens, I recommend using <a target="_blank" href="https://pgicons.abiro.com/">https://pgicons.abiro.com/</a>. It will create varied sizes of icons and splashes for all the targeted mobile operating systems. </p>
<p>After creating these, you can directly replace these icons with the default ionic icons and splashes in your targeted platforms folders.</p>
<h1 id="heading-progressive-web-app-pwa">Progressive Web App (PWA)</h1>
<p>The two main requirements of a PWA are <a target="_blank" href="https://developers.google.com/web/fundamentals/primers/service-workers/">Service Workers</a> and a <a target="_blank" href="https://developers.google.com/web/fundamentals/web-app-manifest/">Web Manifest</a>. Once these files have been added, run <code>ionic build</code> and the <code>build</code> directory will be ready to deploy as a PWA to any hosting platform like Firebase. </p>
<p>Follow the link ? <a target="_blank" href="https://ionicframework.com/docs/react/pwa">https://ionicframework.com/docs/react/pwa</a> for more details.</p>
<p>First, <a target="_blank" href="https://console.firebase.google.com/">create the project</a> in the <strong>Firebase</strong> Website. You can choose the free plan for now. Enable the hosting option from the left nav. Next, in a terminal, install the Firebase CLI:</p>
<p><strong>npm install -g firebase-tools</strong></p>
<p>It will ask you some default name and folder options for firebase related files. Continue answering all the questions. Now, build your project again with the <strong>--prod</strong> flag as given below:</p>
<p><strong>ionic build --prod
firebase deploy</strong></p>
<p>That’s it. ? Go to the link provided by Firebase under the hosting section. It is very simple and straightforward to deploy your app on Firebase. Every time you push your code to your own GitHub repo, just follow those 2 commands to build and deploy the latest changes into your Firebase project.</p>
<h1 id="heading-android-app">Android App</h1>
<p><a target="_blank" href="https://developer.android.com/studio/">Android Studio</a> is the IDE for creating native Android apps. It includes the <a target="_blank" href="https://ionicframework.com/docs/reference/glossary#android-sdk">Android SDK</a>, which will need to be configured for use in the command line.</p>
<p>Android Studio is also used to <a target="_blank" href="https://ionicframework.com/docs/developing/android#creating-an-android-virtual-device">create Android virtual devices</a>, which are required for the Android emulator. Ionic apps can also be <a target="_blank" href="https://ionicframework.com/docs/developing/android#set-up-an-android-device">launched to a device</a>. </p>
<p>Use the link for complete setup and installation ?<a target="_blank" href="https://ionicframework.com/docs/developing/android">https://ionicframework.com/docs/developing/android</a>.</p>
<p>// Run the below commands to sync native plugins and run the native apps:
<strong>ionic cap copy
ionic cap sync
ionic capacitor run android
ionic cap open android</strong></p>
<p>Now, your app will be open in Android Studio where you can check the same folder, your project ID, and other default settings. Also, you can build icons and splash screens for your own app and replace the existing default ionic ones in the project. </p>
<p>Create an Emulator and run the app. You should see your Coronavirus-tracker app in the Android Emulator now. Go to the <strong>Build</strong> option in the top in Android Studio, and select the <strong>Build Bundle(s)/APK(s).</strong> For the first time, you need to create the signing key. Then, click next to build apk/bundle option.</p>
<p><strong>Hurray</strong>! ? You have your own Android app now in the build folder which is ready to deploy to <strong>Google Play Store</strong> (Developer accounts <strong>cost USD</strong> $<strong>25</strong> with lifetime access) and <strong>Amazon App Store</strong> (free).</p>
<h1 id="heading-ios-app">iOS App</h1>
<p><a target="_blank" href="https://developer.apple.com/xcode/">Xcode</a> is the IDE for creating native iOS apps. It includes the iOS SDK and Xcode command-line tools. Xcode can be <a target="_blank" href="https://developer.apple.com/download/">downloaded for free</a> with an Apple account or it can be installed through the App Store. </p>
<p>Use the link for complete setup and installation ? <a target="_blank" href="https://ionicframework.com/docs/developing/ios">https://ionicframework.com/docs/developing/ios</a>. </p>
<p>Unfortunately, iOS apps can only be built in Apple Computers with macOS operating systems.</p>
<p>// Run the below commands to sync native plugins and run the native apps:
<strong>ionic cap copy
ionic cap sync
ionic capacitor run ios
ionic cap open ios</strong></p>
<p>Now, your app will be open in Xcode where you can set your project ID and other default settings. Also, create icons and splash screens for your own app and replace the existing default ionic ones in the project. </p>
<p>Create an Emulator and run the app. You should see your Coronavirus-tracker app in the iOS Emulator now. If you have an active <strong>Apple Developers Account</strong> which costs <strong>USD</strong> $99 annually, you can build your iOS app and deploy it to the <strong>App Store</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Due to policy issues of the epidemic, Google Play Store, Amazon App Store, and others are not accepting app packages related to the Coronavirus. So until and unless you have authenticity proofs from any Government, Hospitals, or any designated Health Institution, no stores are accepting these apps. </p>
<p>However, the World Wide Web (<strong>WWW</strong>) is free to use. So we have deployed our app on the web only for now.</p>
<p><strong>Finally, our Ionic React app is freely available on the internet for end users – ta-da!</strong></p>
<p><a target="_blank" href="https://coronatracker-20efc.web.app/">CoronaTracker</a> (Use mobile devices for a smooth experience) <a target="_blank" href="https://coronatracker-20efc.web.app/world">https://coronatracker-20efc.web.app/world</a></p>
<h2 id="heading-pending-work">Pending Work</h2>
<p>Since writing this article, I have made this project open source on GitHub. You can contribute here by forking the below repo.</p>
<ol>
<li>Desktop Responsiveness ? (Currently works well for Mobile and Tablets)</li>
<li>Unit test cases.</li>
<li>There is always formatting and indentation.?</li>
</ol>
<p>For the complete code, jump into the GitHub repo. Don’t forget to star and fork in case you would like to add some more cool features to it. For the fork process, follow the steps given in README.MD file.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kapilraghuwanshi/corona-tracker-app">https://github.com/kapilraghuwanshi/corona-tracker-app</a></div>
<p>I hope that you found this article useful and it was able to help you learn and build an awesome app today. If you really liked it, please do share it on all social media platforms.</p>
<p><strong>Let’s be connected on LinkedIn (</strong><a target="_blank" href="https://www.linkedin.com/in/kapilraghuwanshi/"><strong>@kapilraghuwansh</strong></a><strong>i) and Twitter (</strong><a target="_blank" href="https://twitter.com/techygeeeky"><strong>@techygeeek</strong></a><strong>y) for more such tech stories.?</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write "Hello, World!" in Ionic ]]>
                </title>
                <description>
                    <![CDATA[ This guide will teach you how to write a simple Hello World program in Ionic. Step 1: installation Install ionic, npm ,angular and cordova if not installed. [See first introduction for more information.] sudo apt-get install nodejs sudo apt-get insta... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-hello-world-in-ionic/</link>
                <guid isPermaLink="false">66c3564839357f944697658f</guid>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ toothbrush ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 18 Feb 2020 19:34:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9c84740569d1a4ca32ac.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This guide will teach you how to write a simple Hello World program in Ionic.</p>
<h2 id="heading-step-1-installation">Step 1: installation</h2>
<p>Install ionic, npm ,angular and cordova if not installed. [See <a target="_blank" href="https://guide.freecodecamp.org/ionic">first</a> introduction for more information.]</p>
<pre><code class="lang-shell">sudo apt-get install nodejs
sudo apt-get install npm 
sudo npm install -g ionic cordova
</code></pre>
<h2 id="heading-step-2-create-a-folder-named-helloworld">Step 2: Create a folder named helloworld</h2>
<pre><code class="lang-shell">ionic start helloworld blank
</code></pre>
<p>Note: Since this is a small project, enter No or N when prompted during program execution.</p>
<h2 id="heading-step-3-change-directory-to-helloworld-this-is-your-ionic-directory">Step 3: Change directory to helloworld [this is your ionic directory]</h2>
<pre><code class="lang-shell">cd helloworld
</code></pre>
<h2 id="heading-step-4-open-the-folder-in-your-text-editor">Step 4: Open the folder in your text editor .</h2>
<p>You will see various files and subfolders.</p>
<p>Don't panic – these files are generated automatically by npm for you. Just go to <code>src</code>-&gt;<code>page</code>-&gt;<code>home</code>-&gt;<code>home.html</code> .</p>
<h3 id="heading-basic-file-format">Basic File Format</h3>
<pre><code class="lang-text">`home.html` is the html page where you can write html syntax.&lt;br/&gt;

`home.scss` is the css page to write css syntax.&lt;br/&gt;

`home.ts` is the typescript page to write typescript code.
</code></pre>
<h2 id="heading-step-6-delete-the-template-and-add-the-html-syntax-as-shown-below">Step 6: Delete the template and add the html syntax as shown below</h2>
<pre><code class="lang-html"> <span class="hljs-tag">&lt;<span class="hljs-name">ion-header</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ion-navbar</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-title</span>&gt;</span>
      Ionic Project
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-title</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">ion-navbar</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-header</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">ion-content</span> <span class="hljs-attr">padding</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Hello World <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-content</span>&gt;</span>
</code></pre>
<h2 id="heading-step-7-save-the-code-and-run">Step 7: Save the code and run</h2>
<pre><code class="lang-shell">ionic serve
</code></pre>
<p>To see your code running go to the browser and and open localhost:8100 in the URL. That's it!</p>
<h2 id="heading-more-info-on-ionic">More info on Ionic:</h2>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/ionic-full-course/">Ionic full course (video)</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/creating-a-crud-to-do-app-using-ionic-4/">Create a CRUD todo app with Ionic</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a CRUD To-do App Using Ionic 3 ]]>
                </title>
                <description>
                    <![CDATA[ By Sameeha Rahman Hey all! This is a post on an up and coming tech topic — Ionic! By the end of this post you would learn how to create a simple CRUD (Create, Read, Update and Delete) to-do list app, which is also connected to Firebase. Hybrid Mobile... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/creating-a-crud-to-do-app-using-ionic-4/</link>
                <guid isPermaLink="false">66d460c73bc3ab877dae222c</guid>
                
                    <category>
                        <![CDATA[ Firebase ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 24 Jul 2019 08:47:12 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca144740569d1a4ca4d9e.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sameeha Rahman</p>
<p>Hey all! This is a post on an up and coming tech topic — Ionic! By the end of this post you would learn how to create a simple CRUD (Create, Read, Update and Delete) to-do list app, which is also connected to Firebase.</p>
<h1 id="heading-hybrid-mobile-applications-what-are-they">Hybrid Mobile Applications — What are they?</h1>
<p>Simply put, they are mobile apps created by the easier to learn languages; HTML, CSS, and JavaScript. The beauty of developing a hybrid mobile app is the fact that they can be compiled to work with any platform. If you are lazy, like yours truly, you’ll find it easier to use one code to build many apps, instead of developing separate apps for each platform.</p>
<p>Ionic is one of the popular frameworks to make your own hybrid mobile app. It can be built into an Android, iOS, Windows phone, Progressive Web or Desktop application. And testing the app is so much easier since it can be live reloaded right onto your browser.</p>
<h2 id="heading-step-1-setting-it-all-up">Step 1 — Setting it all up</h2>
<p>Initially, sign up for an Ionic Pro account, <a target="_blank" href="https://ionicframework.com/pro?source=post_page---------------------------">here</a>. That will make building and shipping the app easier. You might have to sign in sometime during the process of project creation.</p>
<p>To start coding your first Ionic App, there are a bunch of things you need;</p>
<ol>
<li>Node.js — This is pretty easy. Simply go to the Node.js <a target="_blank" href="https://nodejs.org/en/?source=post_page---------------------------">website</a> and download the ideal installer for you. We need the Node Package Manager, aptly named npm, to install all the dependencies for the many modules you would want to use in your app. If you develop on a Mac and have Homebrew installed, simply type in the command <code>brew install npm</code> on the console.</li>
<li>TypeScript — TypeScript, a superset of JavaScript, is used instead of JS for the majority of the code. After installing Node.js, on the console, type in <code>npm install -g typescript</code> .</li>
<li>Cordova — Cordova is a framework that builds the HTML, CSS and JS/TS code into an app. To install, type <code>npm install -g cordova</code></li>
<li>And finally, Ionic — Type in <code>npm install -g ionic</code> .</li>
</ol>
<p>Bonus — You can download all three in one go with this command too! <code>npm install -g typescript cordova ionic</code>.</p>
<p>Now that you have set up the environment, let's get this party started!! ??</p>
<h3 id="heading-creating-your-first-app">Creating your first app</h3>
<p>From within the console, move to the folder in which you want to store the app. My personal preference is to have a dedicated folder for all my Ionic projects in my Documents.</p>
<p>Then, type in <code>ionic start</code> . The console then prompts you for a name for the project, like so, <code>Project name: Tasks</code>.</p>
<p>It then prompts you to specify the type of application.</p>
<pre><code>? Starter template: (Use arrow keys)
  tabs     | A starting project <span class="hljs-keyword">with</span> a simple tabbed interface
&gt; blank    | A blank starter project
  sidemenu | A starting project <span class="hljs-keyword">with</span> a side menu <span class="hljs-keyword">with</span> navigation <span class="hljs-keyword">in</span> the content area
  <span class="hljs-built_in">super</span>    | A starting project complete <span class="hljs-keyword">with</span> pre-built pages, providers and best practices <span class="hljs-keyword">for</span> Ionic development.
  tutorial | A tutorial based project that goes along <span class="hljs-keyword">with</span> the Ionic documentation
  aws      | AWS Mobile Hub Starter
</code></pre><p>For now, let's make it a blank project, a to-do list with all CRUD functions in one page. It will then prompt you for permission to add the Android and iOS platforms.</p>
<pre><code>? Integrate your <span class="hljs-keyword">new</span> app <span class="hljs-keyword">with</span> Cordova to target native iOS and Android? (y/N) y
</code></pre><p>It will proceed to download extra dependencies that will allow you to live reload the app in emulators and devices. Once the native SDK’s are downloaded you are prompted to add the Ionic Pro SDK, if you wish to do so.</p>
<pre><code>? Install the free Ionic Pro SDK and connect your app? y
</code></pre><p>If you do pick yes, the console will then prompt you for your Ionic Pro email and password, set up at the beginning of this post.</p>
<pre><code>? Email: 
? Password:
</code></pre><p>Thereafter, you have the option to either link this app to an existing one, to create a new one entirely.</p>
<pre><code>? What would you like to <span class="hljs-keyword">do</span>? (Use arrow keys)
  Link an existing app on Ionic Pro
&gt; Create a <span class="hljs-keyword">new</span> app on Ionic Pro
</code></pre><p>The console then proceeds to ask your preferred git host, to store your repository. I prefer GitHub, as it’s something I’m more familiar with.</p>
<pre><code>? Which git host would you like to use? (Use arrow keys)
&gt; GitHub
  Ionic Pro
</code></pre><p>Depending on your choice above, if you picked GitHub as I have, you may require to open your browser to give your credentials and sign in. Once done, return back to the console. You then need to link this app to the repository or create a new one. If you don’t have a repository, go back to GitHub and create one now. Once the new repository is created, come back to the console and type <code>y</code> .</p>
<pre><code>? Does the repository exist on GitHub? y
</code></pre><p>Afterward, pick the correct repository from the list displayed on the console. I will be using only the master branch for now and will go with the former option.</p>
<pre><code>? Which would you like to <span class="hljs-keyword">do</span>? (Use arrow keys)
&gt; Link to master branch only
  Link to specific branches
</code></pre><p>And FINALLY, we’re done creating the app!! ??</p>
<p>But, If you picked Ionic Pro as a git host, pick the option to generate an SSH key pair.</p>
<pre><code>? How would you like to connect to Ionic Pro? (Use arrow keys)
&gt; Automatically setup <span class="hljs-keyword">new</span> a SSH key pair <span class="hljs-keyword">for</span> Ionic Pro
  Use an existing SSH key pair
  Skip <span class="hljs-keyword">for</span> now
  Ignore <span class="hljs-built_in">this</span> prompt forever
</code></pre><p>And we’re done here too! Now to have a look at the app</p>
<p>There are two different commands to view the app on the browser.</p>
<ol>
<li><code>ionic serve</code></li>
<li><code>ionic serve -l</code></li>
</ol>
<p><code>ionic serve</code> displays the app in the view of a web application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/ionic-serve.png" alt="Image" width="600" height="400" loading="lazy">
<em>Web Application View</em></p>
<p><code>ionic serve -l</code> displays the app in the many mobile device platforms. You will need to download it from within the console, when prompted, to get this view.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/ionic-serve-l.png" alt="Image" width="600" height="400" loading="lazy">
<em>Mobile Platforms View</em></p>
<p>And that’s a wrap for today! We successfully created and linked an Ionic 4 app to a version control host. </p>
<h3 id="heading-the-project-structure">The Project Structure</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/project-structure-ionic.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder directory</em></p>
<ol>
<li>app.module.ts — The entry point of the app. Any and all components, pages, modules, and providers need to be added to this file, as it keeps track and controls the many resources used by the app.</li>
<li>app.components.ts — The first page that is loaded as the app starts running, with all the code you wish to execute first. Pages that you might wish the user to view first, like the login screen, are put in this component.</li>
<li>app.html — The template of the app, where the other UI pages will mount onto.</li>
<li>app.scss — The page that holds all the Sass variables and styles to be used globally within the app.</li>
</ol>
<p>Let’s head on over to the main component that we will be amending for this application, home.</p>
<p>As seen above, the home component has three pages;</p>
<ol>
<li>home.html — The view/UI of the page is coded here, using HTML.</li>
<li>home.scss — Any page-specific styling is to be added here, along with Sass variables to be used within the page.</li>
<li>home.ts — The operational logic, in our case adding new tasks to the list, is coded in TypeScript here.</li>
</ol>
<h2 id="heading-step-2-implementing-the-crud-operations">Step 2 - Implementing the CRUD operations</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/wireframeionic.png" alt="Image" width="600" height="400" loading="lazy">
<em>Wireframe of the app</em></p>
<p>What I hope to implement as seen above, is a very simple design; a text input to type the tasks, a button to add it to the list, a list view to view the items and finally a delete button to remove the items from the list. I might change up the design later.</p>
<p>Go ahead and open your editor. Let's take a quick run through all the pages and components found in the current directory.</p>
<h3 id="heading-creating-the-ui-for-c-and-r">Creating the UI for C and R</h3>
<p>To begin, let’s tackle the UI first. When you open up home.html, this is the current code in the page.</p>
<pre><code class="lang-js">&lt;ion-header&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-navbar</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-title</span>&gt;</span>Ionic Blank<span class="hljs-tag">&lt;/<span class="hljs-name">ion-title</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-navbar</span>&gt;</span></span>
&lt;/ion-header&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-content</span> <span class="hljs-attr">padding</span>&gt;</span>
    The world is your oyster.
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>If you get lost, the
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"http://ionicframework.com/docs/v2"</span>&gt;</span>docs<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    will be your guide.
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ion-content</span>&gt;</span></span>
</code></pre>
<p>You can then remove everything within the <code>&lt;ion-content&gt;</code> tags. This is the body of the page and elements within those tags will be seen.</p>
<p>Now add an input tag in the body, so we can enter in the task, followed by a button, to call a method to add the task to the list.</p>
<pre><code class="lang-js">&lt;ion-content padding&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter task"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Add Task<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ion-content</span>&gt;</span></span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/boring-basic--3-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Boring and basic</em></p>
<p>Not pretty, right? Let’s add some styling now!</p>
<p>Ionic has a special input tag <code>&lt;ion-input&gt;</code> , that comes with some styling coded within it, so go ahead and switch boring old <code>&lt;input&gt;</code> to <code>&lt;ion-input&gt;</code> !</p>
<p>Ionic also comes with certain special classes which have styling, like the <code>ion-button</code>. I also want to have the button to the end of the input, and not right below. The final changes look like this;</p>
<pre><code class="lang-js">&lt;ion-content padding&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter task"</span> [(<span class="hljs-attr">ngModel</span>)]=<span class="hljs-string">"taskName"</span>/&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"item-note"</span> <span class="hljs-attr">item-end</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span>&gt;</span>Add Task<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">ion-item</span>&gt;</span></span>
&lt;/ion-content&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/seamless-sleek--2-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Seamless and sleek</em></p>
<p>So much better, right!? And all this without writing any CSS! Let’s have another look at the code above.</p>
<p><code>&lt;ion-item&gt;</code> tag is normally used with the <code>&lt;ion-list&gt;</code> element. But, using this here, with the input within this element, gives it an added style on focus or use. Using the class <code>item-note</code> for a div element allows the button to be in line with the input tag. Doing so, gives a more seamless and sleek design, compared to the first one. Since Angular is also integrated into Ionic, we can use ngModel to easily link values in the views to that in the TypeScript files.</p>
<p>Ionic also comes with a built-in pack of icons, Ionicons. Its very simple to use, and a quick example would be substituting the Add task text with <code>&lt;ion-icon name="add"&gt;&lt;/ion-icon&gt;</code> . Find more on Ionicons, <a target="_blank" href="https://ionicons.com/?source=post_page---------------------------">here</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Capture.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Final input tag</em></p>
<p>The final result! I’m quite happy with what it looks like now, but feel free to play around more with colors and styling.</p>
<h3 id="heading-implementing-create-and-read-functionality">Implementing create and read functionality</h3>
<p>Now that the UI has been done, let's move on to giving this a function. It’s time to look at home.ts. You start off with code that looks like this;</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { NavController } <span class="hljs-keyword">from</span> <span class="hljs-string">'ionic-angular'</span>;

@Component({
    <span class="hljs-attr">selector</span>: <span class="hljs-string">'page-home'</span>,
    <span class="hljs-attr">templateUrl</span>: <span class="hljs-string">'home.html'</span>
})

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePage</span> </span>{
    <span class="hljs-keyword">constructor</span>(public navCtrl: NavController) {  }
}
</code></pre>
<p>Let’s get a quick look at what we have here. You import any components or external modules, that you may need to use in this page at the very top. The next few lines describe the template to which the many functions you may write belong to and manipulate. And lastly, all the logic you may code. Any code you wish to execute before viewing or interacting with the page must be written within the constructor.</p>
<p>Since we will be adding new to-dos each time, we need a place to store it. The simplest way to do this is to initialize an array. If you have had experience with JavaScript previously, coding with TypeScript will be a piece of cake! </p>
<p>Let’s call our list taskList, but since we need the list to be accessed from more than one method of the code, we need to initialize it outside the constructor <code>taskList = [];</code>. Now to write code to handle the Add Task button click, let's call it <code>addTask</code>. All we need to do is capture the text in the input, and push it onto the array. Since we have used <code>ngModel</code> for the input tag, we can easily get the value inside it by using <code>this.taskName</code>. And adding values to an array is as easy as <code>taskList.push(task)</code>. We also need to ensure that no empty string is being added to the list, so wrap the above statement in an if condition, checking if the taskName truly exists. The final home.ts code;</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { NavController } <span class="hljs-keyword">from</span> <span class="hljs-string">'ionic-angular'</span>;

@Component({
    <span class="hljs-attr">selector</span>: <span class="hljs-string">'page-home'</span>,
    <span class="hljs-attr">templateUrl</span>: <span class="hljs-string">'home.html'</span>
})

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePage</span> </span>{
    taskList = [];

    <span class="hljs-keyword">constructor</span>(public navCtrl: NavController) {}

    addTask() {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.taskName.length &gt; <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">let</span> task = <span class="hljs-built_in">this</span>.taskName;
            <span class="hljs-built_in">this</span>.taskList.push(task);
            <span class="hljs-built_in">this</span>.taskName = <span class="hljs-string">""</span>;
        }
    }
}
</code></pre>
<blockquote>
<p>Note: Using the keyword <code>let</code> in TypeScript is the equivalent of using <code>var</code>, for variable declaration.</p>
</blockquote>
<p>Now we can begin adding new tasks!</p>
<p>But how do we know something is being added???</p>
<p>Easy Peasy, ?Squeezy! That’s what the R in CRUD is there for!</p>
<h3 id="heading-run-the-code-and-have-a-look">Run the code and have a look</h3>
<p>Time to C(reate) a way for us to R(ead) what we type! (See what I did there?)?</p>
<p>Let’s roll back to the home.html. So far, we have put an input tag and a button to add tasks; now to put a list to view it. We now need to link the method <code>addTask()</code> to the button in the <code>(click)</code> property, so that a list item is added to the array with each click.</p>
<p><code>&lt;ion-list&gt;</code> is a special Ionic element for list views. The <code>&lt;ion-item&gt;</code> tag is used within it to generate each item in said list. <code>*ngFor</code> is an easy method of showing all elements within a list, by setting a standard view for each list item.</p>
<p>The final home.html code;</p>
<pre><code class="lang-js">&lt;ion-header&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-navbar</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-title</span>&gt;</span>To-do List<span class="hljs-tag">&lt;/<span class="hljs-name">ion-title</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-navbar</span>&gt;</span></span>
&lt;/ion-header&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-content</span> <span class="hljs-attr">padding</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> [(<span class="hljs-attr">ngModel</span>)]=<span class="hljs-string">"taskName"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter task"</span>/&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"item-note"</span> <span class="hljs-attr">item-end</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"addTask()"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">ion-icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"add"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-icon</span>&gt;</span><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">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">padding</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-list</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span> *<span class="hljs-attr">ngFor</span>=<span class="hljs-string">"let todo of taskList"</span>&gt;</span>
                {{todo}}
            <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ion-list</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">ion-content</span>&gt;</span></span>
</code></pre>
<p>The variable <code>todo</code> is a temporary store for the element in the current index of the for loop (ngFor) within the list <code>taskList</code>, as declared in the home.ts.</p>
<p>Ready to see our app so far?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We did it!! It works!!????</p>
<p>But that was just Create and Read. Will still have to implement Update and Delete.</p>
<p>We will first begin with changing the GUI so that it can fit both the update and delete features. Thereafter move onto the TypeScript code, to show its functionality.</p>
<h3 id="heading-change-that-look-to-include-handlers-for-u-and-d">Change that look to include handlers for U and D</h3>
<p>Whoops! Little forgetful ole me! I didn’t change the app name on the home page… ???</p>
<p>Go ahead and call it whatever you wish (I’ll be basic with ‘To-do List’).</p>
<p>The first step, to be done in the home.html, is to add the delete button to the left side of each list item. That’s easy! Reuse the very same code I used to include the <code>addTask</code> button next to the input in the <code>&lt;ion-item&gt;</code>, nesting this button within the div with the class item-note, but change that + into an ?️icon (don’t want to get confused now, do we?). Since this is a button, give the event handler the name <code>deleteTask()</code>. The button will also have another style class <code>clear</code>, which gives it a clear background. Since this button will be within the <code>&lt;ion-item&gt;</code> that is in the <code>&lt;ion-list&gt;</code>, it will be generated for all items in the list.</p>
<p>We need to add another button to the list to edit each task. Luckily more copying of code! Copy the whole button tag, but replace the icon ?️ to a ✏️ and the click handler to <code>updateTask()</code>.</p>
<p>The code for each <code>&lt;ion-item&gt;</code> tag now looks like this</p>
<pre><code>&lt;ion-item *ngFor=<span class="hljs-string">"let todo of taskList; let i = index"</span>&gt;
    {{todo}}
    &lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"item-note"</span> item-end&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">clear</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"updateTask(i)"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ion-icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"create"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-icon</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">clear</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"deleteTask(i)"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ion-icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"trash"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-icon</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
    &lt;/div&gt;
&lt;/ion-item&gt;
</code></pre><p>The statement <code>let i = index</code> takes the index of the specific element in the list, so that we can pass it over to the method, so only the element to be deleted would be affected.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Capture3-und.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Pretty neat, huh??</p>
<p>I quite like it and it looks so much better than the wireframe I originally designed.</p>
<h3 id="heading-implementing-update-and-delete-functionality">Implementing update and delete functionality</h3>
<p>Now to add functionality to our ?️ and ✏️.</p>
<p>We need to create a new method within the home.ts called <code>deleteTask()</code>, as specified in home.html above. We pass the index of the array from within the <code>ngFor</code> loop, so we know the exact position of the task to be deleted. Hop on over to home.html, and pass the parameter <code>i</code>, which is the index of the element in the array, within the <code>deleteTask</code> method, like so <code>deleteTask(i)</code>. As you have passed the index through to the home.ts, you simply need to use the <code>splice()</code> method on the array to remove the desired task, passing the index of the item to be removed as a parameter, like so <code>this.taskList.splice(index, 1);</code>.</p>
<p>The code for the <code>deleteTask</code> method is;</p>
<pre><code class="lang-js">deleteTask(index){
    <span class="hljs-built_in">this</span>.taskList.splice(index, <span class="hljs-number">1</span>);
}
</code></pre>
<p>Short and sweet! ? That’s all the coding we need to delete tasks!</p>
<p>Now to update, it will take a bit more typing (bear with me)!</p>
<p>My plan is to open up an alert asking the user to enter the update text of the task. To do that, we need to import the <code>AlertController</code>, a module found in <code>ionic-angular</code>. You import it using this line of code.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { NavController, AlertController } <span class="hljs-keyword">from</span> <span class="hljs-string">'ionic-angular'</span>;
</code></pre>
<p>You then need to initialize it in the constructor, like so;</p>
<pre><code class="lang-js"><span class="hljs-keyword">constructor</span>(public navCtrl: NavController, public alertCtrl: AlertController)
</code></pre>
<p>You will then need to create an alert in the <code>updateTask</code> method to capture the new task name. To do so, you will need to pass the following into the create method of the AlertController;</p>
<ol>
<li>title — The title of the message.</li>
<li>message — A longer message (if required).</li>
<li>inputs — Input field with their name and placeholder (if any).</li>
<li>buttons — Buttons along with their role or handler (if any).</li>
</ol>
<p>The alert can be displayed afterward with the simple <code>alert.present()</code>command. I will be having two buttons, one is a cancel button, the second is to edit and the handler code will simply take the entered task and switch it with the previous value in the array. The code for the <code>updateTask()</code> method;</p>
<pre><code class="lang-js">updateTask(index) {
    <span class="hljs-keyword">let</span> alert = <span class="hljs-built_in">this</span>.alertCtrl.create({
        <span class="hljs-attr">title</span>: <span class="hljs-string">'Update Task?'</span>,
        <span class="hljs-attr">message</span>: <span class="hljs-string">'Type in your new task to update.'</span>,
        <span class="hljs-attr">inputs</span>: [{ <span class="hljs-attr">name</span>: <span class="hljs-string">'editTask'</span>, <span class="hljs-attr">placeholder</span>: <span class="hljs-string">'Task'</span> }],
        <span class="hljs-attr">buttons</span>: [{ <span class="hljs-attr">text</span>: <span class="hljs-string">'Cancel'</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'cancel'</span> },
                  { <span class="hljs-attr">text</span>: <span class="hljs-string">'Update'</span>, <span class="hljs-attr">handler</span>: <span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
                      <span class="hljs-built_in">this</span>.taskList[index] = data.editTask; }
                  }
                 ]
    });
    alert.present();
}
</code></pre>
<p>It should all work perfectly now!</p>
<p>Want to see the final CRUD app?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part3-und.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And there you have it! ??</p>
<p>A fully operational CRUD to-do list, with minimal coding! That’s how easy Ionic can be.</p>
<p>I still believe we can make it a bit more user-friendly. Scroll down for more add-on functionality.</p>
<h3 id="heading-bonus-auto-focus">Bonus!! — Auto-focus</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part3-no-autofocus.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Input without autofocus</em></p>
<p>Do you know what I find annoying? I need to click on the input each time I want to add a new task, even at the beginning. Why not auto-focus the input after clicking the button?</p>
<p>That’s exactly what we will do!</p>
<p>Auto-focus on Ionic is not as easy as it is in classic HTML/JavaScript interactions. You need to import an extra component called <code>ViewChild</code>. You can then easily connect the input from the view (home.html) to the controller (home.ts), and manipulate it as well. You import it, like so;</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Component, ViewChild } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
</code></pre>
<p>You can then connect the input tag to the component, outside the constructor, using this line of code,</p>
<pre><code class="lang-js">@ViewChild(<span class="hljs-string">'taskInput'</span>) input;
</code></pre>
<p><code>taskInput</code> is the id of the input tag on the home.html page. Go ahead and add<code>#taskInput</code> to the input tag. The input tag can now directly be handled from within the TypeScript file.</p>
<p>Ionic comes with a few methods that can be invoked on certain app events, such as when a page loads onto the view, unloads and so on. These are called lifecycle events, and more about then can be found <a target="_blank" href="https://ionicframework.com/docs/api/navigation/NavController/?source=post_page---------------------------">here</a>. We can cause the app to auto-focus on the input from within the <code>ionViewDidLoad()</code>, by setting a timeout. The code would be;</p>
<pre><code class="lang-js">ionViewDidLoad(){
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">this</span>.input.setFocus();
    },<span class="hljs-number">350</span>);
}
</code></pre>
<p>For the auto-focus to work after you add the line <code>this.input.setFocus();</code> as the last statement in the <code>addTask()</code> handler. Lets head on out to see the changes we made!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part3-autofocus-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Input with autofocus</em></p>
<p>Now that’s what you call seamless…?</p>
<h2 id="heading-step-3-integrating-firebase-authentication">Step 3 - Integrating Firebase Authentication</h2>
<p>Firebase has everything, from authorization to a database to file storage, one of the many reasons it’s a good choice to add to mobile apps. In this post, we will explore Firebase, create a project and make a handler component for Firebase in the app.</p>
<h3 id="heading-setting-up-the-firebase-console">Setting up the Firebase console</h3>
<p>But first step’s first, you need to create a project on the Firebase console. All you need is a Google account to access Firebase. So head on over <a target="_blank" href="https://console.firebase.google.com/?source=post_page---------------------------">here</a> to get started. Add a new project and give it a name (I just called mine ‘Tasks’), agree to everything they ask and hit Create Project.</p>
<p>Now to set up the project to fit our needs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Capture2.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>All the areas of Firebase that we will be accessing will be found under Develop.</p>
<p>Namely;</p>
<ol>
<li>Authentication</li>
<li>And Database.</li>
</ol>
<p>Let’s have a look at Authentication.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/capture1.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, all methods of authentication have been disabled. For now enable the very basic of types, Email/Password, so we can begin using it to register an account.</p>
<p>Under templates, the many email templates for verification of email address to forget password are can be found. If you wish, you can change a few of the details, like the project name to be displayed and the name of the sender.</p>
<p>Now, onward to the Database section. Firebase has two types of databases;</p>
<ol>
<li>Realtime Database — a NoSQL database, that looks like one big JSON Object.</li>
<li>Cloud Firestore — A collection of documents, which are essentially JSON Objects.</li>
</ol>
<p>Firestore is the better option as it has a better structure compared to the normal Realtime Database. In the Realtime Database, anybody can write data anywhere, if they have the reference to the database, greatly affecting all the data stored. And for that reason, I picked Firestore and created the database in test mode, so we can assess the database.</p>
<p>Firestore in test mode does allow anyone to read and write into it, so let’s make it that only users who have registered to the app have access to the database. To do so, switch <code>allow read, write: if false;</code> for <code>allow read, write:if request.auth.uid!=null;</code>. Only registered users have a unique uid, with which to distinguish them. Most often, the uid is used as the ID to the users' object. I will be implementing the same for this project.</p>
<p>Once the rules are changed, we need to create a collection, so all our user documents can be put into it. Since we cannot have a collection without at least one document, make a fake user. You can delete it from the dashboard later.</p>
<p>As we have set up the Firebase dashboard, let’s move on the integrating Firebase into the app.</p>
<h3 id="heading-linking-firebase-to-the-app">Linking Firebase to the app</h3>
<p>There is a special module <code>AngularFire</code> you can download using npm to incorporate Firebase into the Ionic app. To download, type <code>npm install firebase angularfire2 --save</code>.</p>
<p>To use this module, you need to import it into the app.module.ts page, like so</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { AngularFireModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'angularfire2'</span>;
<span class="hljs-keyword">import</span> { AngularFireAuthModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'angularfire2/auth'</span>;
<span class="hljs-keyword">import</span> { AngularFirestoreModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'angularfire2/firestore'</span>;
</code></pre>
<p>We also need to add the necessary config data for the app to access and use the correct database. This can be found in the Project Overview section, ‘Add Firebase to your web app’. You are required to call the JSON object firebaseConfig and initialize it after the imports.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> firebaseConfig = {
    <span class="hljs-attr">apiKey</span>: <span class="hljs-string">"#######################################"</span>,
    <span class="hljs-attr">authDomain</span>: <span class="hljs-string">"###########.firebaseapp.com"</span>,
    <span class="hljs-attr">databaseURL</span>: <span class="hljs-string">"https://###########.firebaseio.com"</span>,
    <span class="hljs-attr">projectId</span>: <span class="hljs-string">"###########"</span>,
    <span class="hljs-attr">storageBucket</span>: <span class="hljs-string">"###########.appspot.com"</span>,
    <span class="hljs-attr">messagingSenderId</span>: <span class="hljs-string">"############"</span>
};
</code></pre>
<p>One last step! You need to include the imported modules above, into the import array of <code>@NgModule</code> that contains all the components used in the app, initializing the AngularFireModule as well with the config object above.</p>
<pre><code class="lang-js">@NgModule({
    ...
    imports: [
        ...
        AngularFireModule.initializeApp(firebaseConfig), 
        AngularFireAuthModule, 
        AngularFirestoreModule
    ]
})
</code></pre>
<p>AngularFireAuthModule comes with many methods pertaining to authorization, like signup, sign in, forgot password, etc. All the methods we will be using will be found in the auth property of AngularFireAuth. The methods being used are;</p>
<ol>
<li><code>signInWithEmailAndPassword()</code> — Login</li>
<li><code>createUserWithEmailAndPassword()</code> — Register</li>
<li><code>sendPasswordResetEmail()</code> — Reset Password</li>
<li><code>signOut()</code> — Logout</li>
</ol>
<h3 id="heading-implementing-all-the-authentication-logic">Implementing all the authentication logic</h3>
<p>We need to add a listener, to check if the user has logged in or not, and to display the correct response for either. We need to add the listener in the app.component.ts, as it’s the first page of the app that is loaded.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> authObserver = afAuth.authState.subscribe(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (user) {
        <span class="hljs-built_in">this</span>.rootPage = HomePage;
        authObserver.unsubscribe();
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">this</span>.rootPage = LoginPage;
        authObserver.unsubscribe();
    }
});
</code></pre>
<p>Import the necessary other modules, like the HomePage, LoginPage, and AngularFireAuth.</p>
<p>Let’s start coding the Register page first.</p>
<p>First, to add a new page to the app. There are two ways to do this;</p>
<ol>
<li>Create a new folder within the pages folder inside src and create separate .scss, .ts and .html files.</li>
<li>Or, be lazy (like me ?) and just type <code>ionic g page &lt;name of page&gt;</code> in the console. All three files will be auto-generated!</li>
</ol>
<p>Since we need to conduct many validations on the data entered in the login, register and forgot password pages, we need to utilize a form group to have a track of all the fields in the form and to add any and all validation to each field, such as checking if the email looks like an actual email, password lengths, the works. We’ll first design the view of the page. In register.html, the form tag looks like so;</p>
<pre><code class="lang-js">&lt;form [formGroup]=<span class="hljs-string">"signupForm"</span> (submit)=<span class="hljs-string">"signupUser()"</span> novalidate&gt;
</code></pre>
<p><code>novalidate</code> is used as the actual validation is being added in the .ts file to the form group <code>signupForm</code>.</p>
<p>Then copy the exact item tag that we have been using to add task names in the home page (but remove that button, id and <code>[(ngModule)]</code> this time!). Add a tag for the users’ full name, email, password and confirm password. The type of input tag for the latter two is password and email for the email tag. You will also need to add a <code>formControlName</code> to each input tag. Add in a button as well of the type submit, to submit the form. The body of your register page must now look like this;</p>
<pre><code class="lang-js">&lt;form [formGroup]=<span class="hljs-string">"signupForm"</span> (submit)=<span class="hljs-string">"signupUser()"</span> novalidate&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"firstName"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"First Name"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"lastName"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Last Name"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>  
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Password"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"retype"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Confirm Password"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-grid</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-row</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ion-col</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"text-align: center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">center-all</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"!signupForm.valid"</span>&gt;</span>Create an Account<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ion-col</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-row</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-grid</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span></span>
</code></pre>
<p>The Register button is disabled until the Lets now add validators to each input, in the register.ts page. We will need to import the following modules to the top of the page,</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { FormBuilder, FormGroup, Validators } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;
</code></pre>
<p>initialize the form group outside of the constructor, so it can be accessed from anywhere in the component; <code>public signupForm: FormGroup</code> and initialize the form builder inside the parameters passed to the constructor, like so;</p>
<pre><code class="lang-js"><span class="hljs-keyword">constructor</span>(public navCtrl: NavController, public navParams: NavParams, public formBuilder: FormBuilder){}
</code></pre>
<p>Validators will be added to the form within the constructor like so;</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.signupForm = formBuilder.group({
  <span class="hljs-attr">email</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.required])],
  <span class="hljs-attr">password</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.minLength(<span class="hljs-number">6</span>), Validators.required])],
  <span class="hljs-attr">retype</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.minLength(<span class="hljs-number">6</span>), Validators.required])],
  <span class="hljs-attr">firstName</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.maxLength(<span class="hljs-number">30</span>), Validators.pattern(<span class="hljs-string">'[a-zA-Z ]*'</span>), Validators.required])],
  <span class="hljs-attr">lastName</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.maxLength(<span class="hljs-number">30</span>), Validators.pattern(<span class="hljs-string">'[a-zA-Z ]*'</span>), Validators.required])]
});
</code></pre>
<p><code>Validators.compose</code> creates a validation check for the value, according to the validations passed in its parameters. Most of these Validators are self-explanatory. The pattern Validator checks if the value fits a specific regex. But one question remains, how to validate if an email looks like an email? Apparently, we need to make one….</p>
<p>But don’t worry! It’s quite simple and the only logic to it is to see if it fits a certain regex.</p>
<p>We need to make a new folder ‘validators’ in the src folder and a file ‘<code>email.ts</code>’ within it. We will be declaring a static method to check the email. When validating the email, we send the <code>formControl</code> to the Validator, so in that case, we will need to import <code>FormControl</code>. Once the email is tested against the regex, we need to return a value to convey if the email is valid or not. The final code for the email validator is;</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { FormControl } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailValidator</span> </span>{  
  <span class="hljs-keyword">static</span> isValid(control: FormControl) {
    <span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/</span>.test(control.value);
    <span class="hljs-keyword">if</span> (re) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
    <span class="hljs-keyword">return</span> {
      <span class="hljs-string">"invalidEmail"</span>: <span class="hljs-literal">true</span>
    };
  }
}
</code></pre>
<p>Now import the <code>EmailValidator</code> into the register.ts and add it to the array within the <code>Validators.compose</code> method for the email input.</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.signupForm = formBuilder.group({
    <span class="hljs-attr">email</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.required, EmailValidator.isValid])],
    ...
});
</code></pre>
<p>That’s it on the validation side.</p>
<p>Another added feature you can do is show an error message right below the input, or even have the input tag turn red if the validation returns a false. The code for the error message;</p>
<pre><code class="lang-js">&lt;ion-item <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"error-message"</span> *ngIf=<span class="hljs-string">"!signupForm.controls.email.valid  &amp;&amp; signupForm.controls.email.dirty"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Please enter a valid email.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/ion-item&gt;
</code></pre>
<p><code>*ngIf</code> allows you to display the error only if the validation is false. The errors should be put right below each tag, altering the message and input name (in the above example ‘email’) accordingly.</p>
<p>The code for a red input on validation error;</p>
<pre><code class="lang-js">[<span class="hljs-keyword">class</span>.invalid]=<span class="hljs-string">"!signupForm.controls.email.valid &amp;&amp; signupForm.controls.email.dirty"</span>
</code></pre>
<p>Add this inside each input, again changing the inputs’ name accordingly.</p>
<p>Now to handle the button click!</p>
<p>Create the method <code>signupUser()</code>. We will be using the AngularFireAuth modules’ method <code>createUserWithEmailAndPassword()</code>. This returns a promise, that we need to capture and according to the result, handle either the sign in of the user or display an error message. To make it more user-friendly, also show a loading carousel to the user as signup takes place.</p>
<p>As the button is only enabled when the whole form is valid, we do not need to recheck on that fact. We will first check if the password and the retyped password are the same, and if they are, create the new user and add their information to the Firestore. If the two are different, display an error message in the alert, stating that they are different.</p>
<pre><code class="lang-js">signupUser() {
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.signupForm.value.password == <span class="hljs-built_in">this</span>.signupForm.value.retype) {
    <span class="hljs-built_in">this</span>.afAuth.auth.createUserWithEmailAndPassword(<span class="hljs-built_in">this</span>.signupForm.value.email, <span class="hljs-built_in">this</span>.signupForm.value.password)
      .then(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">let</span> userId = <span class="hljs-built_in">this</span>.afAuth.auth.currentUser.uid;
        <span class="hljs-keyword">let</span> userDoc = <span class="hljs-built_in">this</span>.firestore.doc&lt;any&gt;(<span class="hljs-string">'users/'</span> + userId);
        userDoc.set({
          <span class="hljs-attr">firstName</span>: <span class="hljs-built_in">this</span>.signupForm.value.firstName,
          <span class="hljs-attr">lastName</span>: <span class="hljs-built_in">this</span>.signupForm.value.lastName,
          <span class="hljs-attr">email</span>: <span class="hljs-built_in">this</span>.signupForm.value.email
        });
        <span class="hljs-built_in">this</span>.navCtrl.setRoot(HomePage);
      }, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.loading.dismiss().then(<span class="hljs-function">() =&gt;</span> {
          <span class="hljs-keyword">let</span> alert = <span class="hljs-built_in">this</span>.alertCtrl.create({
            <span class="hljs-attr">message</span>: error.message,
            <span class="hljs-attr">buttons</span>: [{ <span class="hljs-attr">text</span>: <span class="hljs-string">"Ok"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'cancel'</span> }]
          });
          alert.present();
        });
      });

    <span class="hljs-built_in">this</span>.loading = <span class="hljs-built_in">this</span>.loadingCtrl.create({
      <span class="hljs-attr">dismissOnPageChange</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">content</span>: <span class="hljs-string">"Signing up.."</span>
    });
    <span class="hljs-built_in">this</span>.loading.present();
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">let</span> alert = <span class="hljs-built_in">this</span>.alertCtrl.create({
      <span class="hljs-attr">message</span>: <span class="hljs-string">"The passwords do not match."</span>,
      <span class="hljs-attr">buttons</span>: [{ <span class="hljs-attr">text</span>: <span class="hljs-string">"Ok"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'cancel'</span> }]
    });
    alert.present();
  }
}
</code></pre>
<p>You will need to additionally import <code>AlertController</code>, <code>Loading</code>, <code>LoadingController</code>, <code>AngularFirestore</code> and <code>HomePage</code>.</p>
<p><code>loading</code> needs to be declared outside the constructor, so that it can be accessed by all the methods. <code>AlertController</code>, <code>LoadingController</code> and <code>AngularFirestore</code> needs to be initialized in the constructor parameters.</p>
<p>And (finally) the register page is done!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/tenor.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Whew! ?? This is the longest post I’ve ever written. And there’s still more to go…..</p>
<p>But don’t worry! The rest is all just copy + paste.</p>
<p>The next page to tackle is the Login page. Copy the entire Register page form to login.html, coz its time to make some changes for it to fit Login. Remove the first name, last name and retyped passwords’ input tags and error messages. On the form tag, change all instances of <code>signupForm</code> to <code>loginForm</code>.</p>
<p>Change the submit buttons’ text to ‘Login’ and the <code>onSubmit</code> method to <code>loginUser()</code>. Add two buttons as well, outside the form, to navigate to the register and reset password pages. The final body of <code>login.html</code>;</p>
<pre><code class="lang-js">&lt;form [formGroup]=<span class="hljs-string">"loginForm"</span> (submit)=<span class="hljs-string">"loginUser()"</span> novalidate&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span> [<span class="hljs-attr">class.invalid</span>]=<span class="hljs-string">"!loginForm.controls.email.valid &amp;&amp; loginForm.controls.email.dirty"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"error-message"</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"!loginForm.controls.email.valid  &amp;&amp; loginForm.controls.email.dirty"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Please enter a valid email.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Password"</span> [<span class="hljs-attr">class.invalid</span>]=<span class="hljs-string">"!loginForm.controls.password.valid &amp;&amp; loginForm.controls.password.dirty"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"error-message"</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"!loginForm.controls.password.valid  &amp;&amp; loginForm.controls.password.dirty"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Your password must be more than 6 characters long<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-grid</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-row</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ion-col</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"text-align: center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">center-all</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"!loginForm.valid"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ion-col</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-row</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-grid</span>&gt;</span></span>
&lt;/form&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">block</span> <span class="hljs-attr">clear</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"danger"</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"resetPwd()"</span>&gt;</span>
  I forgot my password
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">block</span> <span class="hljs-attr">clear</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"createAccount()"</span>&gt;</span>
  Create a new account
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>There you have it! The UI is done.</p>
<p>The <code>loginForm</code> has the same Validators for the email and password fields. So, proceed to copy the same <code>formBuilder</code>, omitting the first name, last name and retyped password fields.</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.loginForm = formBuilder.group({
    <span class="hljs-attr">email</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.required, EmailValidator.isValid])],
    <span class="hljs-attr">password</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.minLength(<span class="hljs-number">6</span>), Validators.required])]
});
</code></pre>
<p>The <code>loginUser()</code> method has similar code to that of the <code>signupUser</code> method. So copy that on to the login.ts as well. The change to be made, is to remove the password comparison and accessing the database.</p>
<pre><code class="lang-js">loginUser() {
 <span class="hljs-built_in">this</span>.afAuth.auth.signInWithEmailAndPassword(<span class="hljs-built_in">this</span>.loginForm.value.email, <span class="hljs-built_in">this</span>.loginForm.value.password).then(<span class="hljs-function">() =&gt;</span> {
   <span class="hljs-built_in">this</span>.navCtrl.setRoot(HomePage);
 }, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
   <span class="hljs-built_in">this</span>.loading.dismiss().then(<span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">let</span> alert = <span class="hljs-built_in">this</span>.alertCtrl.create({
       <span class="hljs-attr">message</span>: error.message,
       <span class="hljs-attr">buttons</span>: [{ <span class="hljs-attr">text</span>: <span class="hljs-string">"Ok"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'cancel'</span> }]
     });
     alert.present();
   });
 });
 <span class="hljs-built_in">this</span>.loading = <span class="hljs-built_in">this</span>.loadingCtrl.create({
   <span class="hljs-attr">dismissOnPageChange</span>: <span class="hljs-literal">true</span>,
   <span class="hljs-attr">content</span>: <span class="hljs-string">"Logging in.."</span>
 });
 <span class="hljs-built_in">this</span>.loading.present();
}
</code></pre>
<p>You will need to import the exact extra modules to the login.ts as well, with the exception of the AngularFirestore, as you will not be accessing the database now.</p>
<p>Now to handle the buttons to the reset password and the registration page;</p>
<pre><code class="lang-js">resetPwd() {
    <span class="hljs-built_in">this</span>.navCtrl.push(ResetPasswordPage);
}

createAccount() {
    <span class="hljs-built_in">this</span>.navCtrl.push(RegisterPage);
}
</code></pre>
<p>The pages work like a stack; you push the next page to the top of the stack and pop from the top as well.</p>
<p>Bear with me, we have one more page to go. Yay! More copy+paste!</p>
<p>For the reset password, we only require the email field, but still, need a form to validate the email entered. Much like for the Login page, copy the entire login.html form, remove all fields except the email input tag and error message, change all instances of <code>loginForm</code> to resetPwdForm. You are left with;</p>
<pre><code class="lang-js">&lt;form [formGroup]=<span class="hljs-string">"resetPwdForm"</span> (submit)=<span class="hljs-string">"resetUserPwd()"</span> novalidate&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span> [<span class="hljs-attr">class.invalid</span>]=<span class="hljs-string">"!resetPwdForm.controls.email.valid &amp;&amp; resetPwdForm.controls.email.dirty"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-item</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"error-message"</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"!resetPwdForm.controls.email.valid  &amp;&amp; resetPwdForm.controls.email.dirty"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Please enter a valid email.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-item</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-grid</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ion-row</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ion-col</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"text-align: center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> <span class="hljs-attr">center-all</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"danger"</span> [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"!resetPwdForm.valid"</span>&gt;</span>Reset Password<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ion-col</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-row</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ion-grid</span>&gt;</span></span>
&lt;/form&gt;
</code></pre>
<p>The same is to be done for the reset-password.ts file. The form builder looks like this;</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.resetPwdForm = formBuilder.group({
    <span class="hljs-attr">email</span>: [<span class="hljs-string">''</span>, Validators.compose([Validators.required, EmailValidator.isValid])]
});
</code></pre>
<p>while the <code>resetUserPwd()</code> method looks like so;</p>
<pre><code class="lang-js">resetUserPwd() {
 <span class="hljs-built_in">this</span>.afAuth.auth.sendPasswordResetEmail(<span class="hljs-built_in">this</span>.resetPwdForm.value.email).then(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> {
   <span class="hljs-keyword">let</span> alert = <span class="hljs-built_in">this</span>.alertCtrl.create({
     <span class="hljs-attr">message</span>: <span class="hljs-string">"We just sent a link to reset your password to your email."</span>,
     <span class="hljs-attr">buttons</span>: [{ <span class="hljs-attr">text</span>: <span class="hljs-string">"Ok"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'cancel'</span>,
       <span class="hljs-attr">handler</span>: <span class="hljs-function">() =&gt;</span> {
         <span class="hljs-built_in">this</span>.navCtrl.pop();
       }}]
   });
   alert.present();
 }, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
   <span class="hljs-keyword">let</span> errorAlert = <span class="hljs-built_in">this</span>.alertCtrl.create({
     <span class="hljs-attr">message</span>: error.message,
     <span class="hljs-attr">buttons</span>: [{ <span class="hljs-attr">text</span>: <span class="hljs-string">"Ok"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">'cancel'</span> }]
   });
   errorAlert.present();
 });
}
</code></pre>
<p>The handler code above pops the reset password page to show the login page once the request for the link is sent.</p>
<p>One last part (I’m so sorry! I’m tired too)…??</p>
<p>The logout button, the easiest and smallest code!</p>
<p>You need to put a button at the end of the header on the home page as shown below;</p>
<pre><code class="lang-js">&lt;ion-header&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-navbar</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-title</span>&gt;</span>To-do List<span class="hljs-tag">&lt;/<span class="hljs-name">ion-title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-buttons</span> <span class="hljs-attr">end</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">ion-button</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"logout()"</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ion-buttons</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ion-navbar</span>&gt;</span></span>
&lt;/ion-header&gt;
</code></pre>
<p>The code to handle the logout in home.ts;</p>
<pre><code class="lang-js">logout() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.afAuth.auth.signOut().then(<span class="hljs-function"><span class="hljs-params">authData</span> =&gt;</span> {
        <span class="hljs-built_in">this</span>.app.getRootNav().setRoot(LoginPage);
    });
}
</code></pre>
<p>The code after the ‘then’ takes the user back to the login page.</p>
<p>And that’s it! Finally! ??</p>
<p>To allow the app to use these pages, you need to include them in the app.module.ts page, in both the declarations and <code>entryComponents</code> arrays, like so;</p>
<pre><code class="lang-js">@NgModule({
    ...
    declarations: [
        ...
        LoginPage, 
        RegisterPage, 
        ResetPasswordPage
    ],
    ...
    entryComponents: [
        ...
        LoginPage, 
        RegisterPage, 
        ResetPasswordPage
    ]
})
</code></pre>
<p>Let’s have a look at all we have achieved so far.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/final-auth.gif" alt="Image" width="600" height="400" loading="lazy">
<em>App with Authentication</em></p>
<p>And there you have it! ?? It’s not so easy on the eyes, but it is definitely functional.</p>
<p>As you can see, when a particular fields’ validation returns false, the input turns red, and the error message shows as well. The buttons stay disabled until all fields of the form are valid!</p>
<p>Below, the user object has also been stored in Firestore, with the current users’ uid as the key to the document. It all works!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/capture4.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Firestore Document</em></p>
<p>Now that authentication and by extension user objects has been implemented, we now go on to syncing up the CRUD operations with Firebase Cloud Firestore.</p>
<h2 id="heading-step-4-syncing-crud-actions-with-cloud-firestore">Step 4 - Syncing CRUD actions with Cloud Firestore</h2>
<p>The coding will be quite simple, as we have already integrated AngularFire into our app. The major changes will be made only to the back-end logic in the home.ts file, and one simple addition to the home.html to handle lists we get from Firestore.</p>
<h3 id="heading-the-c-in-crud-to-firestore">The C in CRUD to Firestore</h3>
<p>We’ll first start with adding functionality to the <code>addTask()</code> method. But first we need to import AngularFirestore to the home.ts and initialize it in the constructor, like so;</p>
<pre><code class="lang-js"><span class="hljs-keyword">constructor</span>(...public firestore: AngularFirestore) {}
</code></pre>
<p>As mentioned in the previous post, Firestore is not like its predecessor, it is not one big JSON structure. Instead, it works with something called documents. Each document is one uniquely JSON object that holds only one type of data, for example, the user object will only hold user data, such as their name, date of birth and other personal information, but not any other data.</p>
<p>Many documents of the same type make up a collection. And sometimes an object can have a collection of different objects inside it, and that’s what we are doing today; making a collection of task objects for each user.</p>
<p>If you can remember, in the previous post, we took the user’s uid, a unique ID that Firebase assigns all its users that sign up as the ID for the users’ JSON object. We will be requiring it heavily today as well, so the first thing to do is capture the uid from AngularFireAuth. As many methods will be using this value, it will be best to declare this variable outside the constructor, then initializing it inside <code>ionViewDidLoad</code>.</p>
<p>We put it in <code>ionViewdidLoad()</code>, because sometimes the user details from AngularFireAuth is not ready by the constructor. And since we will be accessing only that collection within the users' object, go ahead and grab that as well, similar to the register page. All this is added within the call to get the userId.</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.afAuth.authState.subscribe(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (user) {
        <span class="hljs-built_in">this</span>.userId = user.uid;
        <span class="hljs-built_in">this</span>.fireStoreTaskList = <span class="hljs-built_in">this</span>.firestore.doc&lt;any&gt;(<span class="hljs-string">'users/'</span> + <span class="hljs-built_in">this</span>.userId).collection(<span class="hljs-string">'tasks'</span>).valueChanges();
        <span class="hljs-built_in">this</span>.fireStoreList = <span class="hljs-built_in">this</span>.firestore.doc&lt;any&gt;(<span class="hljs-string">'users/'</span> + <span class="hljs-built_in">this</span>.userId).collection(<span class="hljs-string">'tasks'</span>);
    }
});
</code></pre>
<p>The reason why we have two lists is the <code>fireStoreTaskList</code> holds the list that we view, while the <code>fireStoreList</code> is the reference to the collection where we directly add the new tasks. The method <code>valueChanges()</code> returns an Observable List, which we can display in the view.</p>
<p>We can now use this reference anywhere in the page. Using it to add a task in the <code>addTask</code> method is very simple. There is a need to have a specific ID for each task, as we will require it when attempting to update the taskName, so we need to generate the ID and use the <code>set()</code> method of the firestore collection, to create a new task object, inside the if condition, replacing the previous code that pushes the task name into <code>taskList</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> id = <span class="hljs-built_in">this</span>.firestore.createId();
<span class="hljs-built_in">this</span>.fireStoreList.doc(id).set({
    <span class="hljs-attr">id</span>: id,
    <span class="hljs-attr">taskName</span>: task
});
</code></pre>
<h3 id="heading-the-r-in-crud-in-the-app">The R in CRUD in the App</h3>
<p>Now to set up viewing the firestore list. The main part, getting the collection was done above. So the changes now need to be made to the home.html to view the <code>fireStoreTaskList</code>.</p>
<p>The first change is to be in the <code>*ngFor</code>, the name of the list. Since the list will be a response back by firebase, its asynchronous. The normal <code>*ngFor</code>, will cause errors. We need to add an async pipe as well, like so;</p>
<pre><code class="lang-js">&lt;ion-item *ngFor=<span class="hljs-string">"let todo of fireStoreTaskList | async"</span>&gt;
</code></pre>
<p>We no longer need to keep track of the index, as we will be using the task ID to either delete or update its value. And the second change is the value that we will view since todo will now be an object, we need to display todo.taskName, as that’s what we have named the task variable in the task object.</p>
<pre><code class="lang-js">{{todo.taskName}}
</code></pre>
<p>And that’s it! Lets now have a look at both the app and Firestore, to see if it gets saved.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part3-autofocus-2.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Create and Read tasks</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Capture5.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Newly created task</em></p>
<p>It’s got saved!</p>
<p>There’s nothing much to it for the C and R in CRUD. Now to update then delete.</p>
<h3 id="heading-the-u-in-crud-to-firestore">The U in CRUD to Firestore</h3>
<p>Luckily, AngularFirestore has its own update function, which, given the documents’ ID as well as the values to be updated, can be done in one single line. But first, a small change in the home.html file, to allow this to happen. As said earlier, you don’t need the index of the task in the list to update or delete, but instead the document ID, which we have simply stored in the variable id of a task object.</p>
<p>Our first order of business is to send the tasks’ id to the method from the button, like so;</p>
<pre><code class="lang-js">&lt;button ion-button clear (click)=<span class="hljs-string">"updateTask(todo.id)"</span>&gt;
</code></pre>
<p>Move over to home.ts and replace the code in the handler of the alert to;</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.fireStoreList.doc(index).update({ <span class="hljs-attr">taskName</span>: data.editTask });
</code></pre>
<p>We first create a reference to the specific object that the user wishes to update using the <code>doc()</code> method, then sending the relevant data we wish to update into the <code>update()</code> method.</p>
<p>Now to see this functionality in action!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part5-updateTask.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Update task name</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Capture6.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Updated task name</em></p>
<p>This one works too!</p>
<p>Now onto the last change, delete.</p>
<h3 id="heading-the-d-in-crud-to-firestore">The D in CRUD to Firestore</h3>
<p>Deleting is just as easy (or easier, really) than updating.</p>
<p>You will again, need to pass the tasks’ ID onto the delete button;</p>
<pre><code class="lang-js">&lt;button ion-button clear (click)=”deleteTask(todo.id)”&gt;
</code></pre>
<p>Again like for update, AngularFirestore has a function <code>delete()</code>, that is run on the reference of the document to be deleted, like so;</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.fireStoreList.doc(index).delete();
</code></pre>
<p>And now to watch the last functionality….</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part5-deleteTask.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Delete task</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Capture7.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Task deleted in Firestore</em></p>
<p>This one is functional too!</p>
<p>As you can see, the ‘Fold Clothes’ task with an ID of ‘NSskIVHEg4gKsT3U0xAV’ is no longer there, as it has been successfully deleted</p>
<p>There you have it! Firebase integrated into all the CRUD operations.</p>
<h2 id="heading-step-5-bonus-content-styling">Step 5 - Bonus content styling</h2>
<p>This is a short checklist of basic things that weren’t covered in the previous posts;</p>
<ol>
<li>Custom styles ?</li>
<li>Images ?️</li>
<li>Custom fonts ?</li>
</ol>
<h3 id="heading-prettify-the-ui">Prettify the UI</h3>
<p>Going through my app, I was able to see a few things I wanted to change.</p>
<p>Remember those little messages below the input fields in the login, register and reset password pages?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-error-with-underline.png" alt="Image" width="600" height="400" loading="lazy">
<em>Error message with underline</em></p>
<p>I just realized that, since they are essentially <code>&lt;ion-item&gt;</code>, they have a line at the bottom. Not that great.</p>
<p>Thankfully, it’s a simple fix! There’s a global property called <code>no-lines</code>, that you need to add to the <code>&lt;ion-item&gt;</code> like so;</p>
<pre><code class="lang-js">&lt;ion-item ... no-lines&gt;
</code></pre>
<p>So go ahead and add this to all the error message <code>&lt;ion-item&gt;</code> tags.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-error-without-underline.png" alt="Image" width="600" height="400" loading="lazy">
<em>Error message without underline</em></p>
<p>Your error message now looks like this.</p>
<p>Let’s move on to colors!</p>
<p>If you snooped around the project structure, you would have seen a folder called theme. The variables.scss file within has a color variable with 5 set colors. Keep the colors light and dark as they are, as well as danger, as we are using it for the reset password button and page. I will be only changing the primary and secondary color. I normally use <a target="_blank" href="https://coolors.co/1d1e18-6b8f71-aad2ba-d9fff5-b9f5d8?source=post_page---------------------------">coolors.co</a> to find complementary colors for all the projects I’ve ever done.</p>
<blockquote>
<p><em>Disclaimer: Do not add more than those 5 colors to the object, as this causes multiple copies of components to be made for each of these colors. It will eventually add unwanted bulk to the project, as not all components with all colors are used. If you need to use more colors, add a new variable to hold only that color literal.</em></p>
</blockquote>
<p>The colors I will be using are;</p>
<pre><code class="lang-scss"><span class="hljs-variable">$colors</span>: (
    primary:    <span class="hljs-number">#32B596</span>,
    secondary:  <span class="hljs-number">#fff350</span>,
    danger:     <span class="hljs-number">#f53d3d</span>,
    light:      <span class="hljs-number">#f4f4f4</span>,
    dark:       <span class="hljs-number">#222</span>
);
</code></pre>
<p>The first place to splash some color is the top navbar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-plain-navbar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Boring…</em></p>
<p>Looked so bland right??</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-colored-navbar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Ooh la la!</em></p>
<p>Not any more.??</p>
<p>All you need to do is add the color primary to the ion-navbar tag, like so;</p>
<pre><code class="lang-js">&lt;ion-navbar color=<span class="hljs-string">'primary'</span>&gt;
</code></pre>
<p>You can add the color property similarly to other components. Such as, give the delete icon the color stored in danger, or the add and logout button the color in secondary;</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-colorful-app.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding colors everywhere!</em></p>
<p>I still hate the way that the logout button looks… To make it a proper button, simply add the property solid to the tag, like so;</p>
<pre><code class="lang-js">&lt;button ion-button solid color=<span class="hljs-string">'secondary'</span> (click)=<span class="hljs-string">"logout()"</span>&gt;Logout&lt;/button&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-colorful-app-logout-btn.png" alt="Image" width="600" height="400" loading="lazy">
<em>Buttons must look like buttons!</em></p>
<p>Another cool UI design I saw previously, had icons before each input tag on the login, register and reset password pages, so I decided to give that a try as well! It’s a pretty simple code, that you need to add within the <code>&lt;ion-item&gt;</code> tag but before the <code>&lt;ion-input&gt;</code> tag, like so;</p>
<pre><code class="lang-js">&lt;ion-item&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"item-note"</span> <span class="hljs-attr">item-start</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ion-icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"at"</span> <span class="hljs-attr">color</span>=<span class="hljs-string">'primary'</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-icon</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ion-input</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">...</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ion-input</span>&gt;</span></span>
&lt;/ion-item&gt;
</code></pre>
<p>There is no icon that screams password, so I decided to use ? just like in the UI design I had a look at; and ? for the users’ names</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-input-icons.png" alt="Image" width="600" height="400" loading="lazy">
<em>Input icons of the register page</em></p>
<h3 id="heading-adding-images">Adding images</h3>
<p>A picture says a thousand words… But we have no need for such pictures…. ?No matter!</p>
<p>Adding pictures are not necessarily tough, but the path may get a bit confusing sometimes. You would assume that you need to add the actual path from the page to the image folder, which is <code>../../assets/imgs/imagename.png</code>. The path you really need to add is the path from the app.html to the image in the image folder, and that path looks like <code>assets/imgs/imagename.png</code>.</p>
<p>Any and all images you wish to use needs to be added to the folder <code>src/assets/imgs</code>. You can then use the image as if this was HTML;</p>
<pre><code class="lang-js">&lt;img src=<span class="hljs-string">"assets/imgs/imagename.png"</span>/&gt;
</code></pre>
<p>I want to add an image, kinda like a logo, to the login, register and reset password pages.</p>
<p>So that the image doesn’t exceed the page, we will also need to code some styling, and as this image will be in more than one page, we are required to write the styling in the app.scss page like so;</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.imageTop</span> {
    <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">margin</span>: auto;
    <span class="hljs-attribute">display</span>: block;
}
</code></pre>
<p>All you need to do now is simply add the class to the <code>img</code> tag, <code>class='imageTop'</code>.</p>
<p>Another image (or two) that you might want to change, is the splash page and app icon. You will first need to add either (or both) Android and iOS platforms, to use this feature. The command to add a platform is</p>
<pre><code>ionic cordova platform add android
</code></pre><p>Or <code>ios</code>, if that’s your cup of ☕.</p>
<p>Ionic can easily generate different sized splash pages and icons according to different phones when you run the command <code>ionic cordova resources</code> in the terminal. You will need internet for this, as ionic uploads both images to be analyzed to generate the other splash pages and icons.</p>
<p>Before that you need to add both the images, named <code>splash.png</code> and <code>icon.png</code> to the resources folder. The sizes of both images should be 2732<em>2732 and 1024</em>1024 respectively, for the many splash pages and app icons to be generated.</p>
<p>That’s all for images!</p>
<h3 id="heading-typography-roxcks">Typography Rox(cks)!</h3>
<p>First, find a font that speaks to you. The latest trends stick to sans serif fonts that are pretty easy to read. As pretty as many handwritten flowy fonts are, they are just a fail waiting to happen, like this one….</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part-6-cows.png" alt="Image" width="600" height="400" loading="lazy">
<em>I love ?too!</em></p>
<p>Or this one,</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/part6-adolf.png" alt="Image" width="600" height="400" loading="lazy">
<em>Hope has never looked so bleak!</em></p>
<p>???</p>
<p>Jokes aside, I picked the font ‘Alegreya Sans’ to use for this app. It can be found, <a target="_blank" href="https://www.fontsquirrel.com/fonts/alegreya-sans?source=post_page---------------------------">here</a>.</p>
<p>Unpack all the fonts to the folder <code>assets/fonts</code>.</p>
<p>All you need to do now is add the code below to the variables.scss found in the <code>src/theme</code> folder.</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@font-face</span> {
    <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Alegreya Sans Regular'</span>;
    <span class="hljs-attribute">src</span>: url(<span class="hljs-string">"../assets/fonts/AlegreyaSans-Regular.otf"</span>);
}
<span class="hljs-variable">$font-family-base</span>: <span class="hljs-string">'Alegreya Sans Regular'</span>;
<span class="hljs-variable">$font-family-ios-base</span>: <span class="hljs-string">'Alegreya Sans Regular'</span>;
<span class="hljs-variable">$font-family-md-base</span>: <span class="hljs-string">'Alegreya Sans Regular'</span>;
<span class="hljs-variable">$font-family-wp-base</span>: <span class="hljs-string">'Alegreya Sans Regular'</span>;
</code></pre>
<p>The <code>@font-face</code> imports your font and gives it a name, so it can be used throughout the application.</p>
<p>The variable <code>$font-family-base</code> assigns the default font.</p>
<p>The app now looks like this;</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/final-final-app-full.gif" alt="Image" width="600" height="400" loading="lazy">
<em>No one needs to see that password!</em></p>
<p>As you can only view the splash page and icon on a real device, I have brought in my trusty phone into the mix (Sadly it ain’t an Apple to fit with the rest of the gifs/pics).</p>
<p>And that’s it for this series!!!!!??</p>
<p>Find the repo for this post, <a target="_blank" href="https://github.com/samsam-026/Tasks/commit/f54bf2d7e534d31a9ae4962a173053a0044e235e?source=post_page---------------------------">here</a>.</p>
<p>I hope you all had fun and learned a lot on this journey with me!</p>
<p>Thank you for the read, and see you soon!??</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Ionic 4 and start creating iOS / Android Apps ]]>
                </title>
                <description>
                    <![CDATA[ Learn how to use Ionic 4 in this full course for beginners from Awais Mirza. Ionic Framework is the free, open source mobile UI toolkit for developing high-quality cross-platform apps for native iOS, Android, and the web—all from a single JavaScript ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/ionic-full-course/</link>
                <guid isPermaLink="false">66b203b9a8b92c932923646d</guid>
                
                    <category>
                        <![CDATA[ android app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Fri, 17 May 2019 13:40:00 +0000</pubDate>
                <media:content url="https://s3.amazonaws.com/cdn-media-1.freecodecamp.org/ghost/2019/05/ionic.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Learn how to use Ionic 4 in this full course for beginners from Awais Mirza. Ionic Framework is the free, open source mobile UI toolkit for developing high-quality cross-platform apps for native iOS, Android, and the web—all from a single JavaScript codebase.</p>
<p>In this tutorial you will learn how to build a mobile app with Ionic and Angular from scratch. You will learn the basic concepts of Ionic and the Ionic CLI.</p>
<p>Here are a few of the topics covered:</p>
<ul>
<li>Ionic Installation</li>
<li>Project Structure</li>
<li>Emulating iOS and Android</li>
<li>Routing and Lazy Loading</li>
<li>Action Sheet</li>
<li>Components</li>
<li>ION Alert and Documentation</li>
<li>Ionic Native</li>
<li>Debugging</li>
<li>Native HTTP Plugins</li>
<li>Native SMS Plugins</li>
<li>Native Storage</li>
</ul>
<p>You can watch the full video course on the <a target="_blank" href="https://www.youtube.com/watch?v=AvbuIRg8_Jg">freeCodeCamp.org YouTube channel</a> (3 hour watch).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your First Ionic 4 App with API Calls ]]>
                </title>
                <description>
                    <![CDATA[ By Simon Grimm So you just noticed that Ionic 4 was released and you finally want to get started with cross-platform app development? Well, today is your day! We’ll go through building your first Ionic 4 application with HTTP Calls to the Open Movie ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-your-first-ionic-4-app-with-api-calls-f6ea747dc17a/</link>
                <guid isPermaLink="false">66c35066465d1b2f886ba420</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 04 Feb 2019 16:37:38 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*cun5ECRCb1_QS4BcQI-r7A.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Simon Grimm</p>
<p>So you just noticed that Ionic 4 was released and you finally want to get started with cross-platform app development? Well, today is your day! We’ll go through building your first Ionic 4 application with HTTP Calls to the <a target="_blank" href="http://www.omdbapi.com/">Open Movie Database</a>!</p>
<p>Whether you are completely new to Ionic or have used previous versions, we go through all the basics. We will cover how to set up <strong>a new app</strong>, <strong>routing</strong> and even <strong>API calls to display async data</strong> inside our app.</p>
<p>If you want to learn Ionic even faster you can also <a target="_blank" href="https://ionicacademy.com/">check out my Ionic Academy</a> which was made for developers just like you!</p>
<p><em>Ready</em>? <strong>Go</strong>!</p>
<h3 id="heading-setting-up-our-ionic-4-app">Setting up Our Ionic 4 App</h3>
<p>If you are new to Ionic you need to make sure you have the <a target="_blank" href="https://www.npmjs.com/get-npm">Node Package Manager installed</a>. If you have worked with other web technologies before chances are pretty good you already got everything you need.</p>
<p>If you also haven’t used Ionic before, you need to install it through npm. Once installed you are finally ready to create your Ionic 4 project!</p>
<p>To set up a blank project you can use the <strong>Ionic CLI</strong> so we end up with a fresh Ionic 4 project with Angular support (<em>you could also use React or Vue, better support coming later this year</em>).</p>
<p>Once the project is created we <strong>cd</strong> into the folder. We use the CLI, which uses the <a target="_blank" href="https://cli.angular.io/">Angular CLI</a> under the hood, to create new pages for our app that we want to display.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install Ionic if you haven't before</span>
npm install -g ionic

<span class="hljs-comment"># Create a blank new Ionic 4 app with Angular support</span>
ionic start movieApp blank --<span class="hljs-built_in">type</span>=angular
<span class="hljs-built_in">cd</span> movieApp

<span class="hljs-comment"># Use the CLI to generate some pages and a service</span>
ionic g page pages/movies
ionic g page pages/movieDetails
ionic g service services/movie
</code></pre>
<p>You can now directly bring up your app by running the following command inside your project:</p>
<pre><code class="lang-bash">ionic serve
</code></pre>
<p>This will open the browser with the preview of your app which will <strong>reload automatically</strong> once you change anything inside your project.</p>
<p>Speaking of the project, we got a bunch of files and folders in here, let’s see what all this means. We will focus on the <strong>src</strong> folder of our app since we don’t have to worry about the rest for now.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*UZ96oo9zs_tdZJtOb7uZeA.png" alt="Image" width="623" height="1024" loading="lazy">
<em>Your Ionic 4 Project</em></p>
<h3 id="heading-app">App</h3>
<p>This is the folder where we will make all the code changes that follow later in this tutorial. It already contains a <strong>home</strong> folder that’s basically a page like we created before. I like to have all pages in their own <strong>pages</strong> folder so you can remove the home folder as well for now.</p>
<p>The <strong>pages</strong> folder contains the actual views/pages of our app, which means the element we will see on the screen. Right now we already got 2 pages in here, and each page you create with the CLI comes with 4 files:</p>
<ul>
<li><em>.module.ts: The <em>*Angular module</em></em> for a page. Each page is basically their own module (related to the Angular architecture) with imports and styling</li>
<li><em>.page.html: The <em>*HTML</em></em> markup for a page</li>
<li><em>.page.scss: The <em>*styling</em></em> for the specific page (more on global styling later)</li>
<li><em>.page.spec.ts: An automatically added <em>*testing</em></em> file for your page. Good if you want to set up automated unit tests</li>
<li><em>.page.ts: The <em>*controller</em></em> for a page that contains the Javascript code that manages the functionality</li>
</ul>
<p>The <strong>services</strong> folder contains our previously created service — this is about structuring your app according to best practices and separating concerns between the view and the actual data of your app. The service will take care of handling the API calls and simply return the data to our view later!</p>
<h3 id="heading-assets">Assets</h3>
<p>This folder contains all the images, fonts or whatever assets you need for your app later down the road.</p>
<h3 id="heading-environments">Environments</h3>
<p>From time to time your project might have a development, staging and production environment with different servers that your app targets. The environment folder helps to set up information for different environments. We can later build our Ionic app with a <strong>command line flag</strong> and it automatically takes the right values. Very handy!</p>
<h3 id="heading-theme">Theme</h3>
<p>This folder only contains the <strong>variables.scss</strong> that contains predefined color information from Ionic. We can always change this file and even use a tool like the <a target="_blank" href="https://beta.ionicframework.com/docs/theming/color-generator">Ionic Color Generator</a> to create our own flavored version of this file!</p>
<p>Outside of the folder we also have the <strong>global.scss.</strong> Here we can write some SCSS that will be globally applied to our app. We can also define it just for one page in their own styling files.</p>
<h3 id="heading-other-files">Other Files</h3>
<p>The most relevant of the other files might be the <strong>index.html</strong> because just like with every other website, this file marks the entry point to our app! For now, though we don’t need to change a thing in here so let’s now start to get into the actual code.</p>
<h3 id="heading-prerequisite-routing-amp-http-calls">Prerequisite Routing &amp; HTTP Calls</h3>
<p>With Ionic 4 we move on from a proprietary routing concept to the standard <a target="_blank" href="https://angular.io/guide/router">Angular Router</a>. The markup might look a bit more difficult in the beginning, but it actually makes totally sense.</p>
<p>For all the connections inside your app, you set up <strong>routing information</strong> upfront — just like you navigate around on a website!</p>
<p>In our app we need 2 routes:</p>
<ul>
<li><strong>/movies</strong> — Navigate to our first page which should display a list of movies</li>
<li><strong>/movies/:id</strong> — We want to be able to show the details for one movie so we add a param <strong>:id</strong> to the route that we can dynamically resolve</li>
</ul>
<p>We also need to connect the according page (<em>more specific</em>: the module of the page) to the route so Angular knows how to resolve a specific route. We supply this information using <strong>loadChildren</strong> which actually only gets a <strong>string to the module path</strong>.</p>
<p>This means we are not really importing another module here, therefore, the pages are using <strong>lazy loading.</strong> That means they will only be loaded once we navigate there!</p>
<p>To setup our routing information open our <strong>app/app-routing.module.ts</strong> and change it to:</p>
<pre><code class="lang-ts"><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> { Routes, RouterModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-keyword">const</span> routes: Routes = [
  { path: <span class="hljs-string">''</span>, redirectTo: <span class="hljs-string">'movies'</span>, pathMatch: <span class="hljs-string">'full'</span> },
  { path: <span class="hljs-string">'movies'</span>, loadChildren: <span class="hljs-string">'./pages/movies/movies.module#MoviesPageModule'</span> },
  { path: <span class="hljs-string">'movies/:id'</span>, loadChildren: <span class="hljs-string">'./pages/movie-details/movie-details.module#MovieDetailsPageModule'</span> }
];

<span class="hljs-meta">@NgModule</span>({
  imports: [RouterModule.forRoot(routes)],
  <span class="hljs-built_in">exports</span>: [RouterModule]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppRoutingModule { }
</code></pre>
<p>By making this change we have also disconnected the home page which was initially in the project (and which you might have deleted already at this point).</p>
<p>Now the app will load our movies page as the first page, great! You should also notice this change in your running <code>ionic serve</code> instance already.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*0pgOz4DuqJnGR1gFFUEfcA.png" alt="Image" width="784" height="1362" loading="lazy"></p>
<p><strong>Tip:</strong> If you want to get a better feeling for how your app will look on a real device you can also run <code>ionic lab</code> instead of serve but you have to install the package upfront:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install the Lab Package</span>

npm i @ionic/lab

<span class="hljs-comment"># Run your app with device preview and platform styles</span>

ionic lab
</code></pre>
<p>This package was previously bundled with every new app but needs to be installed for Ionic 4 now.</p>
<p><strong>/Tip End</strong></p>
<p>We also need to apply another change to our app as we want to make <strong>HTTP calls.</strong> Therefore we need to import another Angular module for making those requests.</p>
<p>The way of doing this is the same as with Ionic 3. We just need to add the <code>HttpClientModule</code> to our main module file and add it to the <strong>array of imports</strong> like this inside our <strong>app/app.module.ts</strong>:</p>
<pre><code class="lang-ts"><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> { RouteReuseStrategy } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-keyword">import</span> { IonicModule, IonicRouteStrategy } <span class="hljs-keyword">from</span> <span class="hljs-string">'@ionic/angular'</span>;
<span class="hljs-keyword">import</span> { SplashScreen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@ionic-native/splash-screen/ngx'</span>;
<span class="hljs-keyword">import</span> { StatusBar } <span class="hljs-keyword">from</span> <span class="hljs-string">'@ionic-native/status-bar/ngx'</span>;

<span class="hljs-keyword">import</span> { AppComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.component'</span>;
<span class="hljs-keyword">import</span> { AppRoutingModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app-routing.module'</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-meta">@NgModule</span>({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppModule {}
</code></pre>
<p>Before we dive into more Ionic 4 code we first have to set up the service that powers our app and handles all the HTTP requests that we later want to call.</p>
<h3 id="heading-making-http-requests">Making HTTP Requests</h3>
<p>A service is the same as in previous versions a provider and can be injected into our controller in order to call its functions.</p>
<p>In order to use the Open Movie Database you need to <a target="_blank" href="http://www.omdbapi.com/apikey.aspx">request an API key</a> and insert it into our service — the process is free so go ahead right now.</p>
<p>With the API we can now search for strings and get results in form of movies, episodes or even games. Also, we can get detailed information for one specific object of those results so a perfect use case for our first Ionic 4 app!</p>
<p>Our service only needs 2 functions:</p>
<ul>
<li><code>searchData()</code>: This function searches for results to a specific title and search type – an enum we defined upfront to represent the types that we can pass to the API using TypeScript!</li>
<li><code>getDetails()</code>: This function returns the detailed information for one specific element, will be used on our details page</li>
</ul>
<p>Both functions will return an <code>Observable</code> which is like a Promise on steroids. No serious, it’s like a stream of events that we can <strong>subscribe</strong> to. Explaining this concept would take another post. For now, let’s use it and keep in mind that both of our functions are <strong>async</strong> — they will return the API data not immediately.</p>
<p>Now go ahead and change your <strong>services/movie.service.ts</strong> to:</p>
<pre><code class="lang-ts"><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> { HttpClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> { Observable } <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;
<span class="hljs-keyword">import</span> { map } <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs/operators'</span>;

<span class="hljs-comment">// Typescript custom enum for search types (optional)</span>
<span class="hljs-keyword">export</span> <span class="hljs-built_in">enum</span> SearchType {
  all = <span class="hljs-string">''</span>,
  movie = <span class="hljs-string">'movie'</span>,
  series = <span class="hljs-string">'series'</span>,
  episode = <span class="hljs-string">'episode'</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> MovieService {
  url = <span class="hljs-string">'http://www.omdbapi.com/'</span>;
  apiKey = <span class="hljs-string">''</span>; <span class="hljs-comment">// &lt;-- Enter your own key here!</span>

  <span class="hljs-comment">/**
   * Constructor of the Service with Dependency Injection
   * @param http The standard Angular HttpClient to make requests
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> http: HttpClient</span>) { }

  <span class="hljs-comment">/**
  * Get data from the OmdbApi 
  * map the result to return only the results that we need
  * 
  * @param {string} title Search Term
  * @param {SearchType} type movie, series, episode or empty
  * @returns Observable with the search results
  */</span>
  searchData(title: <span class="hljs-built_in">string</span>, <span class="hljs-keyword">type</span>: SearchType): Observable&lt;<span class="hljs-built_in">any</span>&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.http.get(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.url}</span>?s=<span class="hljs-subst">${<span class="hljs-built_in">encodeURI</span>(title)}</span>&amp;type=<span class="hljs-subst">${<span class="hljs-keyword">type</span>}</span>&amp;apikey=<span class="hljs-subst">${<span class="hljs-built_in">this</span>.apiKey}</span>`</span>).pipe(
      map(<span class="hljs-function"><span class="hljs-params">results</span> =&gt;</span> results[<span class="hljs-string">'Search'</span>])
    );
  }

  <span class="hljs-comment">/**
  * Get the detailed information for an ID using the "i" parameter
  * 
  * @param {string} id imdbID to retrieve information
  * @returns Observable with detailed information
  */</span>
  getDetails(id) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.http.get(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.url}</span>?i=<span class="hljs-subst">${id}</span>&amp;plot=full&amp;apikey=<span class="hljs-subst">${<span class="hljs-built_in">this</span>.apiKey}</span>`</span>);
  }
}
</code></pre>
<p>I’ve also added some documentation to the functions — <a target="_blank" href="https://ionicacademy.com/ionic-code-documentation/">with a tool like Compodoc</a> you could now create nice documentation!</p>
<p>Alright, now we are finally ready for some more Ionic 4 code!</p>
<h3 id="heading-searching-for-movies">Searching for Movies</h3>
<p>We start our apps functionality with the things that happen in the background and then build the view on top of it.</p>
<p>So right now we need to implement the logic to submit a search term and type to our service and receive the results. Therefore, we <strong>inject</strong> the service through our constructor so it’s available to the class.</p>
<p>In another function that we call <code>searchChanged()</code> we will now simply call the according function of our service and set the result to a local variable b&gt;results. Our view will later handle the data that comes from the API and display it using this variable.</p>
<p>We also keep 2 more variables for the searchTerm and type inside our class that we pass to the service. We will connect with them from the view as well so we can change them.</p>
<p>Now go ahead with the code for your controller inside the <strong>pages/movies/movies.page.ts</strong>:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { MovieService, SearchType } <span class="hljs-keyword">from</span> <span class="hljs-string">'./../../services/movie.service'</span>;
<span class="hljs-keyword">import</span> { Component, OnInit } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { Observable } <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-movies'</span>,
  templateUrl: <span class="hljs-string">'./movies.page.html'</span>,
  styleUrls: [<span class="hljs-string">'./movies.page.scss'</span>],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MoviesPage <span class="hljs-keyword">implements</span> OnInit {

  results: Observable&lt;<span class="hljs-built_in">any</span>&gt;;
  searchTerm: <span class="hljs-built_in">string</span> = <span class="hljs-string">''</span>;
  <span class="hljs-keyword">type</span>: SearchType = SearchType.all;

  <span class="hljs-comment">/**
   * Constructor of our first page
   * @param movieService The movie Service to get data
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> movieService: MovieService</span>) { }

  ngOnInit() { }

  searchChanged() {
    <span class="hljs-comment">// Call our service function which returns an Observable</span>
    <span class="hljs-built_in">this</span>.results = <span class="hljs-built_in">this</span>.movieService.searchData(<span class="hljs-built_in">this</span>.searchTerm, <span class="hljs-built_in">this</span>.type);
  }
}
</code></pre>
<p>Now the view which looks a lot like Ionic 3 code, just a few of the elements changed their names and properties. For everyone new to Ionic in general: <strong>Welcome to your first Ionic components</strong>!</p>
<p>A page can be separated into 3 areas: Header, content, footer. In our case, we don’t want a footer so we only define the header area with a title and the content with our actual elements for the search.</p>
<p>The first element that affects the search is the <code>ion-searchbar</code> which is a simple input you have seen in many apps before to search for a term.</p>
<p>We always want to call our search functionality when the type or searchTerm changes. We can do this by catching the (ionChange) event of some of our elements.</p>
<p>Below we got a select drop down with options and the according value for the different types that we could pass back to the API.</p>
<p>You should have also noticed the [(ngModel)] syntax through which both elements are connected to our controller properties. If one side changes, the other will automatically get the new value as well (also known as <em>2-way data binding</em>).</p>
<p>So we got the search in place and now add another list with elements below our previous components.</p>
<p>For the list, we use an iteration over our results variable. Because this variable is an Observable (remember the implementation in our service) we need to add an Angular Pipe “| async” to it. The view subscribes to the Observable and handles the changes accordingly.</p>
<p>We also add the routing directly to this element by using <strong>[routerLink].</strong> We construct the path that we want to open when we click on the element. We use the <strong>imdbID</strong> property of the item so we can resolve the information on our details page later.</p>
<p>Besides that, we create the markup for one item using the <strong>Poster</strong> which is an image, the title, year and finally also a cool icon at the and based on the type of the item. Yes, those cool icons are already bundled with your app and are called <a target="_blank" href="https://ionicons.com/">Ionicons</a>!</p>
<p>With all of that in mind change your <strong>pages/movies/movies.page.html</strong> to:</p>
<pre><code class="lang-ts">&lt;ion-header&gt;
  &lt;ion-toolbar color=<span class="hljs-string">"primary"</span>&gt;
    &lt;ion-title&gt;My Movie Search&lt;/ion-title&gt;
  &lt;/ion-toolbar&gt;
&lt;/ion-header&gt;

&lt;ion-content&gt;

  &lt;ion-searchbar [(ngModel)]=<span class="hljs-string">"searchTerm"</span> (ionChange)=<span class="hljs-string">"searchChanged($event)"</span>&gt;&lt;/ion-searchbar&gt;

  &lt;ion-item&gt;
    &lt;ion-label&gt;Select Searchtype&lt;/ion-label&gt;
    &lt;ion-select [(ngModel)]=<span class="hljs-string">"type"</span> (ionChange)=<span class="hljs-string">"searchChanged($event)"</span>&gt;
      &lt;ion-select-option value=<span class="hljs-string">""</span>&gt;All&lt;/ion-select-option&gt;
      &lt;ion-select-option value=<span class="hljs-string">"movie"</span>&gt;Movie&lt;/ion-select-option&gt;
      &lt;ion-select-option value=<span class="hljs-string">"series"</span>&gt;Series&lt;/ion-select-option&gt;
      &lt;ion-select-option value=<span class="hljs-string">"episode"</span>&gt;Episode&lt;/ion-select-option&gt;
    &lt;/ion-select&gt;
  &lt;/ion-item&gt;

  &lt;ion-list&gt;

    &lt;ion-item button *ngFor=<span class="hljs-string">"let item of (results | async)"</span> [routerLink]=<span class="hljs-string">"['/', 'movies', item.imdbID]"</span>&gt;
      &lt;ion-avatar slot=<span class="hljs-string">"start"</span>&gt;
        &lt;img [src]=<span class="hljs-string">"item.Poster"</span> *ngIf=<span class="hljs-string">"item.Poster != 'N/A'"</span>&gt;
      &lt;/ion-avatar&gt;

      &lt;ion-label text-wrap&gt;
        &lt;h3&gt;{{ item.Title }}&lt;/h3&gt;
        {{ item.Year }}
      &lt;/ion-label&gt;

      &lt;ion-icon slot=<span class="hljs-string">"end"</span> *ngIf=<span class="hljs-string">"item.Type == 'movie'"</span> name=<span class="hljs-string">"videocam"</span>&gt;&lt;/ion-icon&gt;
      &lt;ion-icon slot=<span class="hljs-string">"end"</span> *ngIf=<span class="hljs-string">"item.Type == 'series'"</span> name=<span class="hljs-string">"tv"</span>&gt;&lt;/ion-icon&gt;
      &lt;ion-icon slot=<span class="hljs-string">"end"</span> *ngIf=<span class="hljs-string">"item.Type == 'game'"</span> name=<span class="hljs-string">"logo-game-controller-b"</span>&gt;&lt;/ion-icon&gt;

    &lt;/ion-item&gt;

  &lt;/ion-list&gt;

&lt;/ion-content&gt;
</code></pre>
<p>By now you should be able to search for a specific term inside your app and get a list of results — <strong>that’s already a big win</strong>!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*0rjz_KjF2aQX6QtlqTFzdw.gif" alt="Image" width="389" height="681" loading="lazy">
<em>Searching for movie title works!</em></p>
<p>If you are coming form Ionic 3 you might have also noted another new property called <strong>slot</strong> so here’s some info on that:</p>
<p>Ionic 4 components are built using <a target="_blank" href="https://stenciljs.com/">Stencil</a> (yeah, they actually created that tool as well!) so they are standard <strong>web components</strong> — you could import them basically everywhere on the web! These components also use the <a target="_blank" href="https://blog.ionicframework.com/shadow-dom-in-ionic-and-why-its-awesome/">Shadow DOM API</a> and are basically living outside of the scope of your regular DOM elements.</p>
<p><strong>That means also standard styling will sometimes not affect these components like it was possible in previous versions</strong>!</p>
<p>In order to get information into these components, we can inject certain parts of HTML into their <strong>slots</strong> that are defined on these elements. You can <a target="_blank" href="https://github.com/ionic-team/ionic/blob/caa2c1e980f3e17a9e62911a330fca785ffbc9c9/core/src/components/item/item.tsx#L160-L165">see how their implementation looks like</a> on the example of the ion-item we used here.</p>
<h3 id="heading-presenting-detailed-information">Presenting Detailed Information</h3>
<p>Ok enough of background information, let’s put some more work into the details page of our app. We have implemented a route and we also created a button that passed an ID with that route so the details page will be open, but we need to get access to the ID!</p>
<p>With previous Ionic versions we could easily pass whole objects to new pages, this is now not a best practice anymore. Instead, we <strong>pass only small chunks of information</strong> (like an ID) with the URL. Otherwise, you would end up with a huge JSON stringified term inside the URL. This isn’t really something we want to have.</p>
<p>To get access to this ID field (that we already defined inside our routing in the beginning) we can use the <code>ActivatedRoute</code> and its properties.</p>
<p>So after we extract the ID from the params we can make another call to our service (that we injected through the constructor again) and get the detailed information for whatever ID we got.</p>
<p>Nothing really new so let’s add the following code to our <strong>pages/movie-details/movie-details.page.ts</strong>:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { MovieService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./../../services/movie.service'</span>;
<span class="hljs-keyword">import</span> { Component, OnInit } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { ActivatedRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-movie-details'</span>,
  templateUrl: <span class="hljs-string">'./movie-details.page.html'</span>,
  styleUrls: [<span class="hljs-string">'./movie-details.page.scss'</span>],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MovieDetailsPage <span class="hljs-keyword">implements</span> OnInit {

  information = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/**
   * Constructor of our details page
   * @param activatedRoute Information about the route we are on
   * @param movieService The movie Service to get data
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> activatedRoute: ActivatedRoute, <span class="hljs-keyword">private</span> movieService: MovieService</span>) { }

  ngOnInit() {
    <span class="hljs-comment">// Get the ID that was passed with the URL</span>
    <span class="hljs-keyword">let</span> id = <span class="hljs-built_in">this</span>.activatedRoute.snapshot.paramMap.get(<span class="hljs-string">'id'</span>);

    <span class="hljs-comment">// Get the information from the API</span>
    <span class="hljs-built_in">this</span>.movieService.getDetails(id).subscribe(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {
      <span class="hljs-built_in">this</span>.information = result;
    });
  }

  openWebsite() {
    <span class="hljs-built_in">window</span>.open(<span class="hljs-built_in">this</span>.information.Website, <span class="hljs-string">'_blank'</span>);
  }
}
</code></pre>
<p>We also added another function to open a website using the window object and the information from the data of the API that we stored in the local <code>information</code> variable.</p>
<p>Now we just need to create a view based on the JSON information of the API. It always helps to log() out the info you got so you see keys that you can use to display some values.</p>
<p>In our case, we use the <a target="_blank" href="https://beta.ionicframework.com/docs/api/card">Ionic card component</a> and add the image and some items with information and more icons (<em>did I say I really like the Ionicons?</em>).</p>
<p>We also added a button below that card that will be displayed if the result information contains the website key. We just have to add our function to the <code>(click)</code> event of the button in order to hook everything up!</p>
<p>On another note, we also have to add an <code>ion-back-button</code> to the header of that page in order to get a nice little back arrow to our previous movie list page. This was automatically done in v3 but needs to implemented manually as of v4!</p>
<p>Now finish your details view by changing your <strong>pages/movie-details/movie-details.page.html</strong> to:</p>
<pre><code class="lang-ts">&lt;ion-header&gt;
  &lt;ion-toolbar color=<span class="hljs-string">"primary"</span>&gt;
    &lt;ion-buttons slot=<span class="hljs-string">"start"</span>&gt;
      &lt;ion-back-button defaultHref=<span class="hljs-string">"/"</span>&gt;&lt;/ion-back-button&gt;
    &lt;/ion-buttons&gt;
    &lt;ion-title&gt;{{ information?.Genre }}&lt;/ion-title&gt;
  &lt;/ion-toolbar&gt;
&lt;/ion-header&gt;

&lt;ion-content padding&gt;

  &lt;ion-card *ngIf=<span class="hljs-string">"information"</span>&gt;
    &lt;ion-card-header&gt;
      &lt;ion-card-title&gt;
        {{ information.Title }}
      &lt;/ion-card-title&gt;
      &lt;ion-card-subtitle&gt;
        {{ information.Year }}
      &lt;/ion-card-subtitle&gt;
    &lt;/ion-card-header&gt;
    &lt;ion-card-content text-center&gt;
      &lt;img [src]=<span class="hljs-string">"information.Poster"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"info-img"</span>&gt;
      {{ information.Plot }}

      &lt;ion-item lines=<span class="hljs-string">"none"</span>&gt;
        &lt;ion-icon name=<span class="hljs-string">"star-half"</span> slot=<span class="hljs-string">"start"</span>&gt;&lt;/ion-icon&gt;
        &lt;ion-label&gt;{{ information.imdbRating }}&lt;/ion-label&gt;
      &lt;/ion-item&gt;

      &lt;ion-item lines=<span class="hljs-string">"none"</span>&gt;
        &lt;ion-icon name=<span class="hljs-string">"clipboard"</span> slot=<span class="hljs-string">"start"</span>&gt;&lt;/ion-icon&gt;
        &lt;ion-label text-wrap&gt;{{ information.Director }}&lt;/ion-label&gt;
      &lt;/ion-item&gt;

      &lt;ion-item lines=<span class="hljs-string">"none"</span>&gt;
        &lt;ion-icon name=<span class="hljs-string">"contacts"</span> slot=<span class="hljs-string">"start"</span>&gt;&lt;/ion-icon&gt;
        &lt;ion-label text-wrap&gt;{{ information.Actors }}&lt;/ion-label&gt;
      &lt;/ion-item&gt;

      &lt;ion-button expand=<span class="hljs-string">"full"</span> (click)=<span class="hljs-string">"openWebsite()"</span> *ngIf=<span class="hljs-string">"information.Website &amp;&amp; information.Website != 'N/A'"</span>&gt;
        &lt;ion-icon name=<span class="hljs-string">"open"</span> slot=<span class="hljs-string">"start"</span>&gt;&lt;/ion-icon&gt;
        Open Website
      &lt;/ion-button&gt;
    &lt;/ion-card-content&gt;
  &lt;/ion-card&gt;

&lt;/ion-content&gt;
</code></pre>
<p>If you now take a look at your browser you might notice that the image looks waaaay to big as its taking all the space available. Let’s change this through some good old CSS so open your <strong>pages/movie-details/movie-details.page.scss</strong> and insert:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.info-img</span> {
    <span class="hljs-attribute">max-height</span>: <span class="hljs-number">30vh</span>;
    <span class="hljs-selector-tag">object</span>-fit: contain;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<p>Now our results look a lot more appealing.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*FYRipkcDiEjrjZrp2JBDEQ.gif" alt="Image" width="389" height="681" loading="lazy">
<em>Our finished Ionic 4 App</em></p>
<p>We can search, select a movie type, dive into a search result and have a fully functional Ionic 4 app with HTTP calls finished!</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>While it was a straight forward experience to build our first Ionic 4 app there are so many things we haven’t talked enough about.</p>
<p>UI patterns like Tabs and side menu, CSS variables, responsive layout and PWA to just name a few on the side of Ionic and Angular.</p>
<p>And we haven’t even touched the Cordova side of things to actually build this app into a <strong>real native mobile app</strong>!</p>
<p>If you want to learn how to <strong>develop Ionic 4 apps as fast as possible</strong> and get them to the iOS &amp; Android app stores quickly you can <a target="_blank" href="https://ionicacademy.com/">join the Ionic Academy today</a> and enjoy expert screencasts, a library of quick wins and a community to support you on your journey!</p>
<p>And of course, I (Simon) am also present inside to answer all your questions all the time</p>
<p>You can also find a video version of this guide below!</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/3QPbBJgNF94" title="Embedded content" loading="lazy"></iframe></div>

<p><em>Originally published at <a target="_blank" href="https://ionicacademy.com/ionic-4-app-api-calls/">ionicacademy.com</a> on January 24, 2019.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to dynamically theme your Ionic application and make your users happy ]]>
                </title>
                <description>
                    <![CDATA[ By Ryan Gordon Designing a sleek color scheme for your mobile application can be time consuming. Why not let the user choose their own favourite theme? This is one of my favorite features in apps. It provides a great experience for users who don’t wa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-dynamically-theme-your-ionic-application-and-make-your-users-happy-ffa17e15dbf7/</link>
                <guid isPermaLink="false">66c351ce91148fc1d02ee00f</guid>
                
                    <category>
                        <![CDATA[ Ionic Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 10 May 2018 16:35:02 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*FPTVBGFH--t0AHelBsBX2g.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ryan Gordon</p>
<p>Designing a sleek color scheme for your mobile application can be time consuming. Why not let the user choose their own favourite theme?</p>
<p>This is one of my favorite features in apps. It provides a great experience for users who don’t want to be tied down to one primary accent color scheme or want to personalize the theme to suit their own style.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*mCKTtAbjsDbmijNnIQPI6Q.jpeg" alt="Image" width="800" height="888" loading="lazy">
<em>A great example of dynamic themes in the ToDoist app</em></p>
<p>In this Medium post, we will work through a project which will have a number of themes the user can select at run-time just like above. When a theme is selected by the user, ideally this change should happen in real-time rather than requiring the user to reopen the app.</p>
<h3 id="heading-installation-and-getting-started">Installation and getting started</h3>
<p>Ionic, if you haven’t used it before, is a mobile application framework which lets you write mobile apps in HTML, CSS, and Typescript. With one shared codebase, you can develop an application for iOS or Android or you can deploy it as a web app.</p>
<p>To install Ionic, open a terminal and enter :</p>
<p><code>npm install -g ionic@latest</code></p>
<blockquote>
<p>Note: you must have <a target="_blank" href="https://nodejs.org/en/download/">Node JS and npm</a> installed. If you get an error with code ‘EACCES,’ then you may need sudo or admin privileges.</p>
</blockquote>
<p>For this tutorial, the sidemenu template provides a good starting point. To generate a project with this template, enter this command into the terminal:</p>
<p><code>ionic start &lt;name of your app&gt; si</code>demenu</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*mLFWCTj1IhdMdMiXSI7OVg.png" alt="Image" width="567" height="442" loading="lazy">
<em>Example terminal output from the CLI</em></p>
<p>After the project has generated, change into the directory with:</p>
<p><code>cd &lt;name of your a</code>pp&gt;</p>
<p>Now you have an Ionic project with a sidemenu and two pages ready to go! To see your creation, enter <code>ionic serve</code> in your terminal.</p>
<h4 id="heading-setting-up-the-first-2-themes-todoist-red-vs-noir">Setting up the first 2 themes: Todoist Red vs Noir</h4>
<p>In order to set up the first two themes, we’ll need to complete a number of steps. Pretty much all of these steps need to be followed in order to get the themes working.</p>
<p>First, we need to denote an SCSS file which will be used when the theme is applied. In the <code>src/theme</code> directory of your project, you’ll find a <code>variables.scss</code> . The respective theme files are located here, too. Create a new file called:</p>
<pre><code>red.theme.scss
</code></pre><p>This file will be used to apply the first theme. From this file, any of the default Ionic styling can be overridden. There are two options for how we can apply the themes:</p>
<p>Option 1: Styling just the navbar and certain elements</p>
<p>Option 2: Applying the theme to all background content</p>
<p>Here is an example of both options applied. The code has a checkpoint halfway down. If you don’t want to style the whole app, comment out the rest of the code below it:</p>
<p>That’s the first SCSS file created! Next will be for dark mode. Create another new file called:</p>
<pre><code>noir.theme.scss
</code></pre><p>This file will be used to apply the second theme. We won’t need to change much for the second theme to work other than changing the hexcode values to a colour such as <code>#33333</code> .</p>
<p>It’s important to note, though, that <strong>we will need to rename</strong> <strong>the SCSS class from <code>theme-red</code> to something unique</strong> for this theme. I’ll call mine <code>theme-noir</code> .</p>
<p>The next step is to import the SCSS files into the app itself. This is important, otherwise the theme won’t be loaded into the app. Head to the <code>app.scss</code> file located at <code>src/app/app.scss</code> where you can import the theme like so:</p>
<pre><code>@<span class="hljs-keyword">import</span> <span class="hljs-string">'../theme/red.theme'</span>;@<span class="hljs-keyword">import</span> <span class="hljs-string">'../theme/noir.theme'</span>;
</code></pre><p>Now that we’ve created and imported the theme files into the project, the SCSS side of things is taken care of! Now onto the Typescript and HTML.</p>
<h3 id="heading-programmatically-changing-the-theme">Programmatically changing the theme</h3>
<p>Changing the theme itself will only require three more steps for a simple setup:</p>
<ul>
<li>a wrapper around the app</li>
<li>a function to change the theme at run-time</li>
<li>something to hold the state of the current theme</li>
</ul>
<h4 id="heading-the-appstate-class">The AppState class</h4>
<p>The AppState class will be an injectable Angular component that holds what the current theme, and that can also be used to update the theme.</p>
<p>There isn’t much to how it works, other than that it has an internal state variable. When a Get operation is called, a clone of the state is returned. When a Set happens, a property of the state is updated with a new value, in this case the theme.</p>
<p>The AppState will hold the current theme and allow modification, but it will need to be imported into the component you want to use it with.</p>
<p>When an Ionic app is first setup using the CLI, you’ll find the following code in the <code>app.component.ts</code> :</p>
<pre><code><span class="hljs-comment">// used for an example of ngFor and navigation</span>
</code></pre><pre><code><span class="hljs-built_in">this</span>.pages = [
</code></pre><pre><code>{ <span class="hljs-attr">title</span>: <span class="hljs-string">'Default Red Theme'</span>, <span class="hljs-attr">component</span>: HomePage },
</code></pre><pre><code>{ <span class="hljs-attr">title</span>: <span class="hljs-string">'List'</span>, <span class="hljs-attr">component</span>: ListPage }
</code></pre><pre><code>];
</code></pre><p>The array that’s displayed is used to provide content for the sidemenu. This sidemenu will serve as our theme switcher in this project rather than a navigation menu.</p>
<p>Change the values in <strong>this.pages</strong> to reflect the names of the themes you want the user to see (like the theme file that will be applied, and any other assets like images files).</p>
<p>In this example, the ‘theme file’ is going to be the name of the CSS class that we want to use. We’ve already imported the SCSS files by the time the app is running. So rather than accessing the file itself, we access the root class in that file. In the case of the red theme, the ‘theme-noir’ class will be applied.</p>
<h4 id="heading-displaying-available-themes-and-applying-the-wrapper">Displaying available themes and applying the wrapper</h4>
<p>The last step we need to take will be to add a wrapper div. This will be the top level element in the <code>app.html</code> file. This wrapper will have the chosen theme applied to it, allowing children elements to receive style updates also. An example of this in <code>app.html</code> would look like this:</p>
<pre><code>&lt;!-- Wrapper over the app which will use the theming--&gt;
</code></pre><pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"{{global.state['theme']}}"</span>&gt;
</code></pre><pre><code>    <span class="hljs-comment">//in here you will have the rest of app.html</span>
</code></pre><pre><code>&lt;/div&gt;
</code></pre><p>In terms of display, if you followed above and renamed the <code>this.pages</code> array to <code>this.themes</code> so it holds your available themes, then you don’t need to change anything else to display!</p>
<p>The sidemenu originally was used to push to available pages in the app, but now it’s a great theme switcher. The names of each available theme are displayed using NgFor and some databinding with the <code>this.themes</code> array. The result will be a very simple list which will have the name of the theme for each entry. When an entry is clicked, that theme will be applied.</p>
<p>On the <a target="_blank" href="https://github.com/Ryan-Gordon/ionic-dynamic-themes">Github repo</a> you can find a better example with a color indicator next to each entry.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*X-QxmagEFaYE8JMn5w9RHA.png" alt="Image" width="376" height="426" loading="lazy"></p>
<h3 id="heading-recap">Recap</h3>
<p>Okay time for a quick review of what we have done here. So far we have implemented the following changes to get the theming working:</p>
<ul>
<li>Created theme SCSS files for each desired theme</li>
<li>Imported the created theme files in the main Sass file located at <code>src/app/app.scss</code></li>
<li>Setup an AppState class to hold which theme is currently applied</li>
<li>Setup a very small changeTheme function which will set a new theme into AppState</li>
<li>Added a wrapper element over the <code>app.html</code> which will have the theme applied to it</li>
</ul>
<p>To create more themes from here, copy one of the theme files you already created, rename it, and change the hex colour values in this new file. You can make as many as you want! Just make sure that you also import this new theme file in <code>app.scss</code> like you did with the first ones, otherwise it won’t work.</p>
<p>With these five steps you can have dynamic theming in any Ionic application. The beauty of the solution is that it works well on all platforms since it uses no native plugins — everything is in HTML,CSS and TS.</p>
<p>As a bonus, on the <a target="_blank" href="https://github.com/Ryan-Gordon/ionic-dynamic-themes">GitHub repo</a>, I have implemented two other ways to present the available themes.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*FPTVBGFH--t0AHelBsBX2g.png" alt="Image" width="800" height="389" loading="lazy">
<em>Option 2 on the left and a model option on the right</em></p>
<h3 id="heading-conclusion">Conclusion:</h3>
<p>Dynamic theming saves us from worrying whether our chosen colour scheme will suit all audiences. Instead of doing numerous mockups with different schemes to evaluate, we can simply implement all of the colour schemes and let the user choose which one they prefer at runtime.</p>
<p>A hidden benefit of this is that we can collect analytics from our users on which theme suits them best. In the <code>changeTheme</code> function discussed, a webhook or some event could be sent specifying the user’s choice. Through this, developers could gather real user feedback on which themes ‘work’ and which don’t.</p>
<p>All the source code for this tutorial can be found in this <a target="_blank" href="https://github.com/Ryan-Gordon/ionic-dynamic-themes">Github repo</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*LGQFvGWTml9dQTsUJO-s8g.png" alt="Image" width="800" height="494" loading="lazy">
<em>One last look</em></p>
<p>Please consider leaving a star on the repo. I welcome any and all additions.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
