简体   繁体   中英

Modal dialog with image show only the first time a user loads the page

Hello everyone I'm new to front-end development and I'm using Angular 11, Angular material and Bootstrap for a project, my problem is I want to show a pop up with and ad the first time a user loads the home page, the modal dialog is made in angular material, I have the modal dialog in ads component and then call it in the home component on the ngOnInit so the dialog will show when the user loads the home page, I found some solutions using JS but didn't make them work for me, any help on how can I solve this?

My ads component html, I'm only showing the image, no button to close the modal but if I need to add a button for a solution, I can add the button.

<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']
    
    }); 
  }

  
}

So this code makes the modal dialog always show when the home page is load, I need to show it the first time the user load the home page, I saw some solutions using cookies or JS functions but didn't make them work for me, as I said, I'm new to this and I think I didn't use those solutions properly for my project, any suggestions will be appreciated.

If in order to achieve what you mean you need to "remember" if the user has already seen the dialog.

Now I have another question for you:

  1. Does the user need to see this every time the page loads?
  2. Once and never again?
  3. Every time he initiates a session on your site? (opens the browser to browse your site)

If your use-case is like option 1, then you might just have an internal variable. You can either use a static variable with a boolean or use a singleton Service from Angular.

@Component({...})
export class MyComponent {
  public static hasAdvertBeenShown = false

  ngOnInit() {
     if(!MyComponent.hasAdvertBeenShown) {
        this.matRef.showDialog()
        MyComponent.hasAdvertBeenShown = true
     }
  }

}

If your use-case is to show the advertisement the first time the user browses your site then your variable would be stored inside localStorage and it would survive opening and closing the browser.

@Component({...})
export class MyComponent {
  public static hasAdvertBeenShown = MyComponent.hasAdvertBeenShownBefore()

  ngOnInit() {
     if(!MyComponent.hasAdvertBeenShown) {
        this.matRef.showDialog()
        MyComponent.markAsSeen()
     }
  }

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

}

If your use-case is the latter then use sessionStorage is similar to localStorage but it's shorter lived (per session)

@Component({...})
export class MyComponent {
  public static hasAdvertBeenShown = MyComponent.hasAdvertBeenShownBefore()

  ngOnInit() {
     if(!MyComponent.hasAdvertBeenShown) {
        this.matRef.showDialog()
        MyComponent.markAsSeen()
     }
  }

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

}

If you'd like to know more about local and session storages you can take a read over here

Here's what I usually do in my apps

Whenever I need to store something into localStorage, let that be preferences (user settings, dark-mode, etc.) and I want that to survive browser restarts I need to use localStorage.

Since using raw localStorage can get messy quite easily what I do is just create a singleton "UserSettingsService" that wraps the "low-level" local storage logic so I can share it across the codebase:

@Inject({providedIn: 'root'})
export class SettingsService {
  private storage: Storage = localStorage // Change this based on your use-case

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

  public boolean hasAdvertisementBeenShown() {
    const safeBoolean = this.storage.getItem('advert') ?? 'false' // defaulting to false in case it didnt exist
    return JSON.parse(safeBoolean)
  }

}

And then on my other classes:

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

  ngOnInit() {
    if(!this.hasAdvertBeenShown) {
      // do something like showing the advert
      this.adverts.markAdverisementAsShown()
    }
  }
}

It might seem a little overkill for a boolean but apps tend to get more and more complex. Like you'd like later you want to show 3 diferent advertisements and you need to be sure which one you've shown. Now you wouldn't be serializing the boolean but rather the advertisement object that has been shown. Logic gets more complex but because it's in a service you would only change it there and boom it's working again throughout your app!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM