Display a modal dialogue with an image on the initial page load for each user

Working on a project with Angular 11, Angular material, and Bootstrap, I encountered an issue. I want to display a popup ad the first time a user visits the home page. The modal dialog is created using Angular material, and I have it in the ads component, which is then called in the home component's ngOnInit function to show the dialog when the page loads. Despite trying some solutions involving JS, none of them worked for me. Any guidance on how I can resolve this?

In my ads component HTML, only the image is displayed without a close button. However, I am open to adding one for a solution if necessary.

<mat-dialog-content id="myModal" class="gradient-border">
  <img style="max-width: 100%" src="../../../assets/img/modal-ad.jpg" />
</mat-dialog-content>

ads component ts

import { Component, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';

@Component({
  selector: 'app-anuncios',
  templateUrl: './anuncios.component.html',
  styleUrls: ['./anuncios.component.css'],
})
export class AnunciosComponent implements OnInit {
  constructor(public dialogRef: MatDialogRef<AnunciosComponent>) {}

  ngOnInit(): void {}
}

Home component ts

import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AnunciosComponent } from '../anuncios/anuncios.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  constructor(public dialog: MatDialog) {}

  ngOnInit(): void {
    this.showDialog();
  }

  showDialog() {
    const dialogRef = this.dialog.open(AnunciosComponent, {
      maxWidth: '100vw',
      maxHeight: '150vw',
      panelClass: ['animate__animated', 'animate__bounceInDown'],
    });
  }
}

The current implementation always displays the modal dialog when the home page loads, but I specifically need it to show only the first time the user visits the page. I explored options involving cookies or JS functions, but couldn't get them to work effectively for my project. Being new to this, I may not have utilized those solutions correctly. Any suggestions would be greatly appreciated.

Answer №1

If you want to achieve a certain outcome, it's important to consider whether the user has already seen a dialog.

Here's another question for you:

  1. Should the user see this each time the page loads?
  2. Just once and never again?
  3. Every time they start a new session on your site (open the browser to browse your site)?

If your scenario aligns with option 1, then having an internal variable could suffice. You can use either a static variable with a boolean or a singleton Service from Angular.

@Component({...})
export class MySection {
  public static showAdDialog = false

  ngOnInit() {
     if(!MySection.showAdDialog) {
        this.matRef.displayDialog()
        MySection.showAdDialog = true
     }
  }

}

If your situation involves displaying the advertisement only the first time the user visits your site, then store the variable in localStorage where it persists through browser sessions.

@Component({...})
export class MySection {
  public static showAdDialog = MySection.hasSeenAd()

  ngOnInit() {
     if(!MySection.showAdDialog) {
        this.matRef.displayDialog()
        MySection.markAsViewed()
     }
  }

  public static boolean hasSeenAd() {
    return JSON.parse(localStorage.getItem('advert'))
  }
  public static boolean markAsViewed() {
    localStorage.setItem('advert', true)
  }

}

If your case leans towards the latter, using sessionStorage is akin to localStorage but has a shorter lifespan (per session).

@Component({...})
export class MySection {
  public static showAdDialog = MySection.hasSeenAd()

  ngOnInit() {
     if(!MySection.showAdDialog) {
        this.matRef.displayDialog()
        MySection.markAsViewed()
     }
  }

  public static boolean hasSeenAd() {
    return JSON.parse(sessionStorage.getItem('advert'))
  }
  public static boolean markAsViewed() {
    sessionStorage.setItem('advert', true)
  }

}

To delve deeper into local and session storages, refer to this link.

My Approach in Applications

For storing items in localStorage such as preferences (user settings, dark mode, etc.) that should persist even after browser restarts, I opt for localStorage.

To prevent complexities when using raw localStorage, I create a singleton service called "UserSettingsService" that encapsulates the low-level localStorage operations for easier sharing across the app:

@Inject({providedIn: 'root'})
export class SettingsService {
  private storage: Storage = localStorage // Customize as needed based on your requirements

  public recordAdShown() {
    this.storage.setItem('advert', true)
  }

  public boolean checkAdShown() {
    const verifiedBoolean = this.storage.getItem('advert') ?? 'false' // Defaults to false if not found
    return JSON.parse(verifiedBoolean)
  }

}

In other classes:

@Component({...})
export class SomeComponent {
   adShownStatus = this.adverts.checkAdShown()
  constructor(private matRef: Mat..., private adverts: AdvertService){}

  ngOnInit() {
    if(!this.adShownStatus) {
      // Actions like displaying the advert
      this.adverts.recordAdShown()
    }
  }
}

This may seem excessive for just a boolean, but as apps grow more complex, maintenance becomes crucial. For instance, if you later need to display multiple ads and track which ones have been shown, the logic would evolve beyond serializing a boolean to handling different advertisement objects. By containing this complexity within a service, any necessary changes can be made in one central location, ensuring smooth operation throughout the app!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Resetting the internal state in Material UI React Autocomplete: A step-by-step guide

My objective is to refresh the internal state of Autocomplete, a component in Material-UI. My custom component gets rendered N number of times in each cycle. {branches.map((branch, index) => { return ( <BranchSetting key={ind ...

Discovering the power of Next.js Dynamic Import for handling multiple exportsI hope this

When it comes to dynamic imports, Next.js suggests using the following syntax: const DynamicComponent = dynamic(() => import('../components/hello')) However, I prefer to import all exports from a file like this: import * as SectionComponents ...

I am experiencing an issue with my d3 force directed graph where the links are not

I am relatively new to d3 and have limited experience with web frontend development. In my current web application project, I am attempting to create a force directed graph. Despite spending several hours trying to make it work, I have been unable to displ ...

The JavaScript code is failing to retrieve the longitude and latitude of the location on a mobile browser

I am having an issue with my Javascript code not properly retrieving the longitude and latitude from the mobile Chrome browser. While this code works fine on laptop or desktop browsers, it seems to be failing on mobile devices: <script> if (nav ...

What could be causing my click event to fail to register after sorting a WebGrid with a click?

Running into an issue with my webgrid and search button. It works perfectly if I search first, updating the grid with results. But when I click on a header to sort the grid, the search button stops working. Can't seem to figure out how to solve this d ...

UI-Router is malfunctioning, causing ui-sref to fail in generating the URL

I'm currently working on a project that involves Angular, Express, and UI-router for managing routes. While I've properly configured my $states and included the necessary Angular and UI-router libraries in my HTML file, I am facing an issue wher ...

The .NET controller does not receive traffic for the GET method

Having some trouble populating a table with JSON data using angular ng-repeat. No errors are showing up in the console, and my breakpoint in the .NET Controller isn't being triggered. Here's the code for the App Controller: var app = angular.mo ...

Encountering an issue: "Failed HTTP response while trying to access https://localhost:44328/api/AllItProjectsLists/Index: 0 Error Message Unknown"

I am completely new to working with Angular. I have been working on a small application that is supposed to display a list of projects retrieved from a database on the Angular side. To achieve this, I am making a call from Angular to .NET Core 2.2. The dat ...

Exploring Javascript bugs in Visual Studio (or any other JS debugger)

I am currently working with a .js file that is executed using cscript.exe and not in a browser environment. I am aware that I can use the //X parameter with cscript.exe to trigger a debugger selection prompt. This works well when choosing "Visual Studio 2 ...

Achieving a persistent footer at the bottom of the page within Material Angular's mat-sidenav-container while using the router-outlet

I am looking to keep my ngx-audio-player fixed at the bottom of the screen, similar to what you see on most music streaming websites. I currently have a structure with divs and various elements for dynamic content and playing music. The issue is that the ...

Using JavaScript to bring in npm packages

My understanding of javascript modules is still lacking. I recently embarked on a new project that required a library from npm. https://www.npmjs.com/package/random-color-pair After running npm i random-color-pair This created a "node modules" folder wh ...

Is there a way to incorporate a component into Particle.js?

I attempted to encase the Particle around the component but it's not functioning correctly import React from "react"; import { render } from "react-dom"; import Particles from "./Particles"; import "./index.css" ...

What is the best way to play a video from a certain time point in a React application?

How can I make my component automatically play from a specific time like 00:07:12,600 instead of starting from the beginning? import style from './Hero.module.css'; import Image from 'next/image'; import ReactPlayer from 'react-pla ...

Having trouble updating the URL path with the $location service in Angular

I'm facing a challenge in updating the URL path using the $location.url service, as it's not reflecting the changes correctly. For instance, my current URL path is http://localhost:64621/module/commercial/#/company/98163780-4fa6-426f-8753-e05a6 ...

AngularJS ng-repeat: displaying a list of filtered outcomes exclusively

I currently have a ng repeat that loops through a set of results. <a class="list-group-item" href="#trip/{{trip.id}}/overview" ng-repeat="trip in trips | filter:search | limitTo:-15"> Basically, as I enter more text into my input field, the list sh ...

Issues with utilizing Fetch API and JSON Data

I'm encountering some difficulties while trying to interact with my json file. I am using the fetch API to retrieve my json file but, unfortunately, when I log the response to the console, I don't see any data returned. Instead, what appears is a ...

Table cell featuring a status menu created with Material UI DataGrid

I'm looking to include a column called "Filled Status." Although I've checked the documentation, I can't quite figure out how to do it. It seems like I may need to use renderCell when setting up the column, but I'm not sure how to make ...

Variations in comparing tuple types in TypeScript

Exploring the TypeScript Challenge, there is a particular problem known as IsNever. The task at hand is to create a type called IsNever that takes input of type T. If the resolved type equates to never, the output should be true; otherwise, it should be fa ...

Exploring the distinctions between ajax, await, async, and

English is not my strong suit, so please bear with me if my writing seems odd. We have discovered two methods for transitioning from asynchronous ajax calls to synchronous ones. Using async: false Utilizing await Both achieve the same outcome, but I am ...

There seems to be an issue with d3js bar charts as they are not displaying on the screen and there

Recently, I started delving into the world of D3js and decided to try my hand at creating some bar charts. However, despite my efforts, the bar charts failed to display on the screen. <!DOCTYPE HTML> <html> <head> <title> My D3 Pra ...