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

Troubleshooting: The issue of ngModel being undefined in Angular2 with the <input> element

I am currently working with Angular2 and a modified version of Semantic-UI that includes a calendar module. I am utilizing the `calendar` and `dropdown` functionalities: constructor() { setTimeout(() => { jQuery('.ui.dropdown').dr ...

Steps to Validate a Form: To allow the submit button to be enabled only when all input fields are filled out; if any field is left empty,

Is it possible to enable the send offer button only after both input boxes are filled? I'm sharing my code base with you for reference. Please review the code and make necessary modifications on stackblitz 1. example-dialog.component.html <form ...

The jQuery toggle function seems to be skipping alternate items

I have recently started learning Javascript and JQuery. Currently, I am working on creating a comment system where you can click reply to display the form. However, I'm facing an issue where the form only shows up for the first comment reply, not for ...

State of an array has been modified

After toggling the state of a checkbox from true to false, calling setState does not immediately reflect the update on the screen. Instead, another element with state must be interacted with in order to trigger a refresh and display the new value of the ch ...

Approach to activate Required Field Validation while navigating through DatePicker form control

Within my Angular application, I have implemented Required Field Validation for a DatePicker component: <div class="form-group" [ngClass]="{ 'has-required':['injuryDate'].untouched && ['injuryDate'].invalid, ...

What could be the reason behind the for loop not running within a typescript function?

My confusion lies in the for loop within this function that seems to never run. Each console log is set up to return a specific value, but the looping action doesn't trigger. Can someone provide insight into what might be causing this issue? export fu ...

Retrieve the date information from the <td> element, if it exists

There are numerous rows in the table. The table cell labeled "dates" may contain either a specific date or the word "Permanent". If there is a date present and it happens to be greater than today's date, it needs to be highlighted in red. I attempted ...

Enhance the Header component by incorporating a logout button that seamlessly navigates with the NextJS App

Currently, I am utilizing NextJS 14 with App router alongside Spring Boot on the backend. Within my application, I have both public and private routes set up. For the private routes, users are required to log in through a designated login page. Upon succes ...

What tool can be used for formatting and syntax highlighting when working with ejs (embedded javascript) templates?

When working on my project, I utilize EJS as the express templating engine. While it is user-friendly and efficient, I have encountered difficulties when it comes to editing files - the text highlighting could be better, and I have not been able to find an ...

I'm having trouble with my script only fetching the first row of my PHP table. Can someone please take a look at my code

Below is my JavaScript snippet: $('input#name-submit').on('click', function() { var name = $('input#name-submit').val(); if($.trim(name) != ''){ $.post('getmodalreasonUT.php', {name: name}, ...

Modify picture properties when listbox is altered using jQuery

I need to set up a unique album gallery display where different folders are selected based on the item chosen in a selectbox. Below is the HTML code: <select name="album" id="album" onChange="changeimage();"> <option value="0" selected disab ...

Why can't Angular iterate through objects using ngFor in Typescript?

Here's what I currently have: public posts: QueryRef<PostsInterface>; this.posts = this._postService.get(); //in ngOnInit In my HTML file, it looks like this: <mat-card *ngFor="let post of posts | async"> This allows me to display eac ...

Persistent NW.js Local Storage Cache Remains Present even After Deleting Application

I have been encountering an issue in my NW.js app where I store data in the Local Storage. Even after deleting the app and cleaning up cache information, the Local Storage data seems to persist. When I reinstall the app, the stored data reappears as if it ...

Unable to install Angular to the most recent version

Can anyone help me with installing Angular 16? I've tried various solutions on GitHub and Stack Overflow, but I always end up with Angular 15.2.9. This problem occurs on my Windows 11 machine, while on my MacBook, I have successfully installed Angula ...

Exploring ways to access elements within shadow-root (open) in Angular using SVG.js

I'm currently tackling a project involving Angular Elements. Within this specialized component, my goal is to incorporate SVG.js 3+. However, due to the necessity of utilizing ViewEncapsulation.ShadowDom in my component, I am encountering challenges w ...

Receiving error messages about missing images in my React project

I am new to programming and I have encountered an issue while running my React project. When I use the command npm start, I noticed that some image resources are not being packaged properly, resulting in certain images disappearing when the website is run ...

Leverage the power of require() beyond the confines of Node

I'm currently exploring how to integrate an Angular.js application with Node.js. At the moment, I have the following code in the file MY-PROJECT/public/js/controllers.js function LoginController( $scope ) { // fetch waiters var Waiter = require( ...

When working with the Sequelize-Typescript One To Many Association and Repository, a situation may arise where the query returns only one child entity even though there are multiple

Dealing with Sequelize-Typescript, I recently encountered the one-to-many association involving "Album" and "Photos" entities. Each "Album" can have multiple "Photos". Below are the entity codes for reference: Album.ts ` @Table({ timestamps: true, de ...

The requested file cannot be accessed using XMLHttpRequest.open url

Currently, I am in the process of learning about AJAX by following the MDN tutorial. However, I have encountered an issue with the first sample code provided to fetch test.html. Regardless of whether I use absolute or relative paths, my local server consis ...

vue.js watch function failing to update

Hello, I'm just getting started with Vue and currently facing a challenge. I am attempting to update a couple of variables based on changes in another computed variable. The computed variable is connected to a Vuex store and functions correctly, displ ...