Discover the steps for unsubscribing from window.cookieStore.addEventListener('change') while using an Angular service

My current project is utilizing Angular version 15.2.10. In order to monitor cookie changes, I have developed an Angular service that taps into the CookieStore API. Below you can find a snippet of my existing code:

type CookieChangeType = {
    name: string,
    value: string,
    expires: Date,
    domain: string,
}

interface CookieChangeEvent extends Event {
    changed: CookieChangeType[]
}

type CookieStore = {
    addEventListener: Window["addEventListener"]
}

declare global {
    interface Window {
        cookieStore: CookieStore;
        addEventListener(type: String, listener: (this: Window, ev: CookieChangeEvent) => any, useCapture?: boolean): void;
    }
} 

export class CookieConsentCommonsService {
     
    
    subscribeToConsentCookieChange(callback: () => void): void {
            window.cookieStore.addEventListener('change', (event: CookieChangeEvent) => {
                console.log(`Cookie changed: ${change.name} = ${change.value}`);
                callback();            
            });
    }
}

The above code functions correctly but I am looking to enhance it by adding the ability to cancel the subscription. I attempted to save the subscription for later use:

            const sub = window.cookieStore.addEventListener( ...);
            console.log("sub " + sub)

However, this approach does not return anything and the output message reads as follows:

sub undefined

What would be the best way for me to obtain a reference for the created subscription so that I can utilize it later to cancel the subscription?

Answer №1

Visit this link for more information on removing event listeners

function handleChange() {
  // ...
}

// Subscribe to event
window.cookieStore.addEventListener('change', handleChange);
// Unsubscribe from event
window.cookieStore.removeEventListener('change', handleChange);

or

const controller = new AbortController();

// Subscribe to event with signaling mechanism
window.cookieStore.addEventListener('change', handleChange, { signal: controller.signal });
// Cancel subscription by aborting the controller
controller.abort();

TypeScript Interface Definitions

// Definition of Cookie interface
interface Cookie {
  name: string;
  value: string;
  expires?: Date | null; // Optional expiration time
  path?: string; // Optional path
  domain?: string; // Optional domain
  secure?: boolean; // Optional secure flag
  sameSite?: 'lax' | 'strict' | 'none'; // Optional SameSite attribute
}

// Extending CookieStore interface from EventTarget
interface CookieStore extends EventTarget {
  get(name: string): Promise<Cookie | null>;
  getAll(): Promise<Cookie[]>;
  set(cookie: Cookie): Promise<void>;
  delete(name: string): Promise<void>;
}

// Declaring CookieStore in global window object
declare global {
  interface Window {
    cookieStore: CookieStore;
  }
}

Answer №2

If you want to handle events using the rxjs method, you can utilize the fromEvent function and manage subscriptions with the use of the subscription object to unsubscribe from the observable stream when the component is no longer needed.

cookieStorage = (window as any)['cookieStorage'];
listener = (callback: () => void, event: any) => {};
private sub: Subscription = new Subscription();
ngOnInit() {
  this.subscribeToCookieChanges(() => {});
}

async subscribeToCookieChanges(callback: () => void) {
  this.sub.add(
    fromEvent<any>(this.cookieStorage, 'change')
      .subscribe((event: any) => {
        console.log(`Cookie has changed: `, event);
        callback();
      })
    );
    // this.cookieStorage.addEventListener('change', (event: any) => {
    //   console.log(`Cookie has changed`);
    //   callback();
    // });
    await this.cookieStorage.set('test', 'asdf');
}

ngOnDestroy() {
  this.sub.unsubscribe();
}

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

Navigate to the subsequent frame once the HTML5 video finishes playing

I have created a basic HTML webpage with a fullscreen background video (not set to loop) using the Vide plugin. Everything is working well, but I want the video to pause on the last frame to showcase a logo I have included at the end. This functionality w ...

Mysterious page reloads occurring following receipt of a socket.io message

I'm currently working on a chat server with multiple rooms in order to improve my skills with nodejs. You can find the code here: https://github.com/DanielHeath/furious-earth-2/tree/backbone And the live app is accessible at this link: One issue I&a ...

JsPlumb: Incorrect endpoint drawn if the source `div` is a child of a `div` with `position:absolute`

My current setup involves two blue div elements connected by jsPlumb. You can view the setup here: https://jsfiddle.net/b6phv6dk/1/ The source div is nested within a third black div that is positioned 100px from the top using position: absolute;. It appe ...

CSS sticky element not preserving its parent's styles

Hello everyone, I need some assistance with a CSS sticky property issue I am encountering. When I apply the sticky property to a div and scroll down, it doesn't retain its parent's properties as expected. Here is the scenario: I have a Bootstrap ...

What are some ways to utilize setInterval and clearInterval effectively?

Take into account: function doKeyDown(event) { switch (event.keyCode) { case 32: /* Space bar was pressed */ if (x == 4) { setInterval(drawAll, 20); } else { setInterval(drawAll, 20); ...

Remove the 'name' attribute from the input tag within the URL

Is there a way to make the server update the URL format to localhost:3000/userinput instead of localhost:3000/?name=userinput when submitting a name? Any suggestions would be greatly appreciated. Thank you in advance. ExpressJs FILE <!DOCTYPE html> ...

What could be causing my HTML5 page to crash when accessed online, but not when viewed locally?

I am just getting started with HTML5 and decided to experiment with canvas. This is the first canvas page I have created. Everything works fine when I run the page locally (i.e. file:///), but once I upload the files to my webhost, the page gets stuck whi ...

Move the option from one box to another in jQuery and retain its value

Hey guys, I need some assistance with a jQuery function. The first set of boxes works perfectly with the left and right buttons, but the second set is not functioning properly and doesn't display its price value. I want to fix it so that when I click ...

Transform the entire row's color when a checkbox is selected in Angular 4

Is there a way to make an entire row clickable and change the color of the row when clicking on a checkbox? Below is my HTML file: <section class="others"> <div class="sub-header">Others</div> <p class="text-center" *ngIf="otherTests ...

Attempting to transform calc application into TypeScript, what data type should this function be?

Currently in the process of converting a calculator app to TypeScript. I've noticed that TypeScript is not prompting me to define the types for the three functions (handleClick, handleEqual, handleClear). Is specifying the type for the argument eno ...

The upload function does not allow re-uploading of a file that has been previously deleted

Attempting to upload a file using the following code onDrag(event:any) { console.log(this.toUpload); if(this.toUpload.length >0){ this.error = "Only one file at a time is accepted"; }else{ let fileName = event[0].name; let split ...

Guide to creating 2D point shapes with three.js

Is there a way to render a 2D shape of points in three.js? I have been struggling to find a working geometry for this task. I simply want to create a polygon of points that lie on the same plane. The 'Shape' object doesn't seem to be suitab ...

Updating existing text to create personalized HTML dropdown menus

I have designed a unique set of dropdowns by using divs and checkboxes instead of the traditional elements My goal is to dynamically change the 'select-wrapper--title' text (e.g. the first option) based on the selected option in the dropdown I ...

Looking for a way to extract the JSON value from a nested FormArray in Angular without including the key

I built an Angular form that takes user input and converts it into a JSON object. The desired output is: {"Name":"sam","age":"21","Friends":[{"Name":"bob","mobile":["123","456","789"]}]} I want the values of the JSON without keys, inside another JSON li ...

Counter is effective for the initial post, yet it does not function properly for the subsequent post

Can anyone help with an issue I'm having with my JavaScript counter? It works for the first comment, but not the second one. This problem persists whether I use PHP or JavaScript. Below is the JavaScript code for the counter: var count = (function() ...

The error message in Angular states "Unable to destructure the 'country' property of an intermediate value as it is null"

I recently started an Angular project from scratch. When I run the default application that is created alongside the project (which is currently empty), I encounter an error in the console: "Uncaught (in promise) TypeError: Cannot destructure property &apo ...

Changing md-sidenav mode in Angular Material 2

Looking to modify the behavior of the md-sidenav in Angular Material 2, switching from side on desktops to over on mobile devices. Is there a method to achieve this programmatically? Appreciate any guidance! ...

Merge arrays in map function based on label and aggregate information

In my possession is an array filled with data from various streaming channels, categorized by shift (Morning and Afternoon). I dedicated the night to experimenting with different functions like reduce, but unfortunately, I hit a wall and couldn't gra ...

What issues can arise in JavaScript if the URL length is not zero when there is no match found?

Upon clicking the "Open Windows" button in Code A, I expected the two links to open in two tabs simultaneously in Chrome, which is exactly what happened. However, when I added a blank line in the textarea control in Code B, only the link http:// ...

Confirm the presence of an element in a FormGroup using Typescript

In my FormGroup, which I will refer to as form, I need to set multiple values from an object: Here is the current code snippet: if(form.get('value1') && myObj.val1){ form.get('value1).patchValue(myObj.val1); } if(form.get(' ...