Creating a modal with a checkbox option for "remember my preference" in Angular

Currently, I am working on an Angular project (version 16) and my goal is to create a dialog modal that includes a checkbox for "do not show again".
Here is the process I envision:

  • When a user visits the web application for the first time, a dialog modal will appear with the "do not show again" checkbox
  • The user will read the content of the modal and choose to check the checkbox
  • If the user returns to the web app shortly after, the dialog modal will not appear again because the browser will remember the user's choice to "do not show again"

I have heard about the LocalStorage functionality but I am unsure about how to implement it in Angular.

Here is the code I have so far :

TS :

openDialog() {
  const dialogRef = this.dialog.open(ModalDialogComponent);

  dialogRef.afterClosed().subscribe(result => {
    console.log(`Dialog result: ${result}`);
  });
}

HTML (Angular-Material UI) :

<h2 mat-dialog-title>My dialog modal</h2>
<mat-dialog-content class="mat-typography">

<mat-tab-group>
    <mat-tab label="First">First</mat-tab>
    <mat-tab label="Second">Second</mat-tab>
</mat-tab-group>

<mat-checkbox class="example-margin">Do not show again</mat-checkbox>

</mat-dialog-content>

<mat-dialog-actions align="end">
  <button mat-button mat-dialog-close>Cancel</button>
  <button mat-button [mat-dialog-close]="true" cdkFocusInitial>Install</button>
</mat-dialog-actions>

If you have any suggestions or solutions to implement this feature, I would greatly appreciate it. Thank you.

EDIT :

Here is a Stackblitz demo to showcase what I am trying to achieve.

Answer №1

To enhance user experience, you can store a string value in local storage when the user selects the "do not show again" checkbox.

Prior to displaying the modal, you should check local storage to see if that value has been saved.

Check out this example code snippet:

openModal() {
    if (localStorage.getItem('doNotShowAgain')) return;

    const modalRef = this.modal.open(ModalComponent);

    modalRef.afterClosed().subscribe(result => {
        if (result.doNotShow) { // Update this to reflect the checkbox
            localStorage.setItem('doNotShowAgain', '1')
        }
        console.log(`Modal result: ${result}`);
    });
}

Answer №2

All responses provided are accurate in terms of utilizing the localStorage feature. However, none of them offer a complete implementation for your specific example on stackblitz.

As previously mentioned in other responses, below is the correct API for setting and retrieving a value from local storage.

Retrieving value:

const firstVisit = localStorage.getItem('firstVisit');

Setting value:

localStorage.setItem('firstVisit', result);`

In relation to your inquiry about correctly fetching the checkbox value from the mat-dialog.

The mat-dialog-close directive takes an input to be returned as a "result" value once the afterClosed subscription is triggered. To utilize this, a potential solution is outlined below.

Assign a template reference to your checkbox within your dialog markup using #checkBox.

<mat-checkbox #checkBox class="example-margin">Do not show me again</mat-checkbox>

You can then utilize this template reference to pass the checked value to your mat-dialog-close directive like so:

[mat-dialog-close]="checkBox.checked"
.

<button mat-button [mat-dialog-close]="checkBox.checked">OK</button>

Remember to include the negation in your if statement; you only want to trigger the dialog if the local storage value is falsey.

 // only open dialog if falsey
    if (!firstVisit) {
      this.openDialog2();
    }

Please refer to the functional StackBlitz example provided below.

STACKBLITZ

https://stackblitz.com/edit/angular-vacnzu?file=src%2Fmodal-dialog%2Fmodal-dialog.component.html

Answer №3

Upon initialization, it is crucial to retrieve the boolean firstVisit from local storage and then verify if it is true. If true, display the dialog box.

Within your main component:

  ngOnInit(): void {
    const firstVisit = localStorage.getItem('firstVisit');
    if(firstVisit){
      this.openDialog();
    }  
  }

Additionally, remember to save the validation value when the user accepts by clicking on the dialog box.

 openDialog() {
    const dialogRef = this.dialog.open(ModalDialogComponent);
  
    dialogRef.afterClosed().subscribe(result => {
        localStorage.setItem('firstVisit', result);
        console.log(`Dialog result: ${result}`);
    });
  }

Essentially, data can be stored in local storage by using:

localStorage.setItem('variableName', value);

Retrieve data from local storage using:

localStorage.getItem('variableName');

Answer №4

To simplify the process, all you need to do is verify whether the user has checked the "do not show again" checkbox, regardless of their initial connection status.

How can you confirm if the user has previously checked the "do not show again" checkbox?

You can save the checkbox value in localStorage when the user clicks on the "Install" icon.

onInstall() {
   // Retrieve the checkbox value from the `ng-model` attribute.
   // For demonstration purposes, assume the user has selected the checkbox and set it to `true`.
   const checkboxValue = true; // Replace `true` with ng-model variable.
   localStorage.setItem('isdoNotShowAgainCheckBoxSelected', checkboxValue)
}

Subsequently, when the user returns to the application, you can check the localStorage value in the ngOnInit() lifecycle hook to determine whether to display or hide the dialog.

ngOnInit(): void {
    const isCheckBoxSelected = localStorage.getItem('isdoNotShowAgainCheckBoxSelected');
    if(!isCheckBoxSelected) {
      this.openDialog();
    }
}

Answer №5

Are you looking for guidance on accessing localStorage? If so, the syntax is quite simple:

To store a value in localStorage:

localStorage.setItem('show-dialog', 'no');

To retrieve a value from localStorage:

localStorage.getItem('show-dialog');

Keep in mind that localStorage values are stored as strings, so you may need to convert them to other data types like boolean. For example:

showDialog: boolean;

ngOnInit(): void {
  this.showDialog = localStorage.getItem('show-dialog') == 'no' ? false : true;
}

If the localStorage item is not present on initial load, the dialog will be shown. You can set the localStorage value to 'no' when the user interacts with a checkbox.

UPDATE: Here is a sample service that can help manage your subscriptions.

@Injectable({
  providedIn: 'root'
})
export class MyService {

  private showChangedSource: Subject<boolean> = new Subject<boolean>();
  showChanged$ = this.showChangedSource.asObservable();

  changeShowValue(show: boolean) {
    this.showChangedSource.next(show);
  }
  
}

In the component with the checkbox:

checkboxControl = new UntypedFormControl();

constructor(private service: MyService) { }

ngOnInit(): void {
  this.checkboxControl.valueChanges.subscribe(value => {
    this.service.changeShowValue(value);
  }
}

In another component where you want to react to checkbox changes:

constructor(private service: MyService) { }

ngOnInit(): void {
  this.service.showChanged$.subscribe(show => {
    // Add your logic to handle the checkbox value
    console.log('show value: ', show);
  }
}

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

What is the best way to send multiple id values with the same classname as an array to the database via AJAX in Codeigniter?

Hey everyone, I'm facing an issue where I need to send multiple IDs with the same class name but different ID values to the database using AJAX. However, when I try to do this, only the first value is being picked up and not all of them. How can I suc ...

Element UI: Triggering an event when the sort caret is clicked

Is it possible to trigger an event when the sorting carets are clicked on a table with sortable columns, ideally with the same parameters as the header-click event? I am able to emit an event by clicking on the header of any sortable column (header-click) ...

Guide on transferring JSON information from a client to a node.js server

Below is the code snippet from server.js var express = require("express"), http = require("http"), mongoose = require( "mongoose" ), app = express(); app.use(express.static(__dirname + "/client")); app.use(express.urlencoded()); mongoose.con ...

Angular - Leaflet.js - display issues and incorrect rendering

I've seen similar questions before, but I haven't been able to get those solutions to work for me. There seems to be an issue with importing leaflet.css... "styles": [ "src/styles.css", "path/to/leafl ...

Looking to manipulate the form submit data before it is submitted using the standard submit event and jQuery? Read on to learn how to remove, enhance, or change

Is there a way to extract data from a form like the one below? <form action="/search/search" data-remote="true" data-type="json" id="search_form" method="get"> <div class="input-group"> <span class="input-group-addon"> <i ...

Using v-for to pass two properties to a single component in VueJS

Hey there! I'm trying to create a v-for loop with a component that has two different props COMPONENT <template> <div class="bg-light rounded p-2 px-5"> <h5> {{ number }}</h5> <h3>{{ item }} ...

Angular2 Cache: Enhance Your Application's Performance

Currently seeking a cache solution for my Angular2 application. Imagine we have a massive collection of Movie objects stored on a server, too many to fetch all at once. The server offers a REST endpoint: getMovie(String id) On the client side, I need a s ...

Adding a div with a canvas element is malfunctioning

I've been experimenting with using canvg to convert an SVG within a div into a canvas. So far, the conversion is working fine but when I try to copy the innerHTML of the div to another div, it's not functioning properly. The canvas is being gener ...

Angular 6 - Receiving @Input causes output to multiply by 4 instead of displaying just once

In my Angular project, I have two components set up. Here is the code for both: app.component.ts: import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styl ...

What is the best method for uploading images and form content simultaneously in a Vue application?

How can I simultaneously upload images and form content? Is it possible to upload both to the client first and then to the server together with the form content? I'm looking to submit the form content along with the image to the server in one go when ...

Prisma allows for establishing one-to-many relationships with itself, enabling complex data connections

I am in the process of developing a simple app similar to Tinder using Prisma. In this app, users can swipe left or right to like or dislike other users. I want to be able to retrieve matches (users who also like me) and candidates (all users except myself ...

Find the position of an element in an array that includes a specific string value using JavaScript or Node.js

I need help figuring out how to find the index of an array that contains or includes a specific string value. Take a look at my code below to see what I've tried so far: Here is a simple example: var myarr = ["I", "like", "turtles"]; var arraycontai ...

Can minification of JS be achieved in a Jekyll environment?

Currently, I am in the process of developing a project with Jekyll and one of the requirements is to minify HTML, CSS, and JS. I was wondering if Jekyll has built-in features for JS minification. It may seem like a simple question, but since I am new to ...

Authenticate through Twitter when using PhoneGap Cordova

Looking to implement Twitter login in my application using JavaScript and HTML. How can I redirect users to the Twitter login page when they click on the "Sign In with Twitter" button? ...

What is the process for obtaining an app icon from the store using Angular?

Currently, I am working on an app using ionic, angular, and Cordova. Within this app, there are links to other apps available in the app store. My main query is: Is there a way to retrieve the icons of these apps from the store? I aim to display these ic ...

Utilizing Google Closure Library with Angular 6

I am looking to integrate the google closure library into my angular 6 application. To achieve this, I have utilized the following commands: npm install google-closure-compiler and npm install google-closure-library. My application can be successfully co ...

Tips for verifying internet connectivity and accessing stored data in localstorage

I'm working on my home.ts file and I need to use localStorage items when the internet connection is offline. However, I am encountering numerous errors when trying to add an IF condition in my code. Specifically, I want to access the getItem method be ...

AngularJS (ui-mask) provides a valid input mask feature

i encountered an issue while trying to create an input mask using ui-mask in AngularJs. I want the textarea to turn green when the entered string is correct. However, in my case, the textarea starts off green and then turns red when a word is typed until t ...

Tally each div individually and display the count within each div, instead of showing the total count across

I have come across various solutions that show the total number of certain special divs, such as: $('.someclass').length However, I am facing a different challenge. I want to sequentially count each div with a numerical sequence. For instance, ...

What is the correct way to utilize the submit() function within this specific form?

I have a small registration form that requires validation before submission. In order to achieve this, I've developed a JavaScript function as shown below: var name = document.getElementById('name').value; var company = document.getElem ...