NextJS – Update data object being passed into Child Component based on Button Click

I need to know how to update a data object based on a button click. This data object is being passed into a Child Component. When a user chooses an option in the dropdown menu, I want to populate that data object based on the key of the chosen option in the dropdown menu.

Here is my Parent Component…

<div>
        <Dropdown>
            <DropdownTrigger>
                <Button variant="bordered">
                    Films
                </Button>
            </DropdownTrigger>
            <DropdownMenu
                variant="faded"
                aria-label="Dropdown menu with description"
            >
                <DropdownSection title="Shorts"> 
                
                {films.shorts.map((film) => (
                    <DropdownItem
                        key={film.key}
                        textValue={film.key}
                        onAction={(key) => showFilm(key)}
                    >
                        {film.name} {film.year}
                    </DropdownItem>
                ))}
                
                </DropdownSection>
            </DropdownMenu>
        </Dropdown>
        
        {shown && <Film data={data} />}
    </div>

My Child Component is <Film>. I am passing the data object into it.

I’m calling the function showFilm(key) when an option is clicked in the dropdown menu.

What I need to know is how do I get the Child Component to update with new data if I update that data in the showFilm() function?

I tried updating the data object when the showFilm() function is called, but the Child Component doesn’t receive the updated data. I need the Child Component to be refreshed so it receives the new data object (that has been updated).

const [shown, setShown] = useState(false);
  
let data;

function showFilm(key) {
    setShown(true)
    // here is where I want to update the data object being passed into the Child Component. I want the data object to equal the key of the option that was clicked.
    data = key;
    console.log("data", data, "key", key)
  }

GTM: best way to manage a script that needs to run on certain routes in Next.js

We’re managing a chat plugin using GTM, in our Next.js application.

We’d like the chat to be visible only on certain pages, but not others.

Problem. Once loaded, the script is loaded.

Right now it was implemented statically, and that’s the reason it doesn’t work as expected:

<script>
 window.addEventListener("foo", () => {
    // DO SOMETHING
  });
</script>

So of course once loaded, the callback will fire on every page.

My idea to do this dynamically, would be using dynamic variables, something like this

<script>
     const enableFoo = {{customGTMVariable}};
</script>
<script>
 enableFoo && window.addEventListener("foo", () => {
    // DO SOMETHING
  });
</script>

Can this work or should I go for something using the DataLayer?

I’m not a GTM expert, but our consultants theoretically are.
I want to be prepared when I talk to them in order to address the issue.

Thanks

Javascript add days to a date

I need to visualize a div containing all 30 days after the current one. But when javascript add a day after 1 december 2024 the result is 1 january 2025.
This is the code

var ldate = new getDate()

function updCalen(){
document.getElementById('settim').innerHTML = ""
var vday  = 0 ;
for (i= 0; i < 30; i++) {

shdate.setDate(ldate.getDate() +  i );
x++;
document.getElementById('settim').innerHTML += shdate + '<BR>' ;        
}
}

updCalen()

I’m struggling with this problem but I can’t find how to solve it!

Calling contentWindow.postMessage on iframe has no effect

In the vue component below sending a message to an iframe using the iframe.contentWindow.postMessage(...) call has no effect.

The component waits for a message from the iframe and sends a response message to the iframe in the mesageHandler(...). Within the messageHandler(...) there are two ways to send the message to the iframe:

  1. Calling sendResponse1(...) works as expected
  2. Calling sendResponse2() has no effect.

The component has also to send the message in the onBeforeUnmount(...) lifecycle hook. There calling sendResponse1(...) is not an option because there is no event present that has to be passed as argument.

The origin of the iframe is not the same as the origin of the embedding component. The content at the origin is not under our control.
The problem is not browser specific. It persists in Edge and Chrome.

Vue Component

<template>
  <div ref="elm" />
</template>

<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';

const props = defineProps<{
  src: string;
}>();

const elm = ref<HTMLElement | null>(null);
const box = ref<HTMLElement | null>(null);
const iframe = ref<HTMLIFrameElement | null>(null);

onMounted(() => {
  if (!elm.value) {
    return;
  }

  box.value = document.createElement('div');

  iframe.value = document.createElement('iframe');
  iframe.value.src = props.src;

  box.value.appendChild(iframe.value);
  elm.value.appendChild(box.value);

  window.addEventListener('message', messageHandler, { passive: true });
});

onBeforeUnmount(() => {
  iframe?.value?.remove?.();
  box?.value?.remove?.();
  window.removeEventListener('message', messageHandler);
  // sendResponse1(...) <-- cannot call from here because there is no event
  sendResponse2();  // NOK does not work
});

function messageHandler(event: MessageEvent) {
  if (!iframe.value || event.origin !== new URL(iframe.value.src).origin) {
    return;
  }

  // Call 1 OK: message sent
  sendResponse1(event);

  // Call 2 NOK: message not sent
  sendResponse2();
}

function sendResponse1(event: MessageEvent) {
  event.source?.postMessage({ message: 'Response' }, <any>event.origin);
}

function sendResponse2() {
  iframe.value?.contentWindow?.postMessage(
    'Response',
    new URL(iframe.value.src).origin,
  );
}
</script>

<style scoped>
/* Some stylesheets */
</style>

Expo React Native Error With Navigator, Looks like you have nested a ‘NavigationContainer’ inside another

I recently upgraded from sdk 51 to sdk 52. I had to upgrade several libraries, and before my code worked fine, what I find after upgrading, is that the routing, has been broken, and gives me an error, which I do not see any sense, right now I have the version

“@react-navigation/native”: “^7.0.2”, “@react-navigation/native-stack”: “^7.0.2”, “expo”: “52.0.7”,

Now, I have created my app with Expo, and my input file is in app/_layout.tsx In this file, I have a conditional to know if there is user loaded, if so, it enters in the user panel, where I have a drawer, and if not, it enters in the Stack.Navigator where the Stack.Screen of the registry and log-in are.

return (
    <TamaguiProvider config={tamaguiConfig}>
      <Theme name="light">
        <AuthContext.Provider value={{user, setUser}}>
          <NavigationContainer independent={true}>
            {user ? (
              <DrawerLayout /> // Render Drawer if logged in
            ) : (
              <Stack.Navigator initialRouteName="Login">
                <Stack.Screen
                  name="Login"
                  options={{ headerShown: false }}
                  component={Login}
                />
                <Stack.Screen
                  name="Register"
                  options={{ headerShown: false }}
                  component={RegisterHandler}
                />
              </Stack.Navigator>
            )}
          </NavigationContainer>
        </AuthContext.Provider>
      </Theme>
    </TamaguiProvider>
  )

In my file I have the user panel with the routes,

const DrawerLayout = () => {
  const [newRecipeGenerated, setNewRecipeGenerated] = useState(false);

  return (
    <NewRecipeGenerationContext.Provider value={{ newRecipeGenerated, setNewRecipeGenerated }}>
      <Drawer.Navigator>
          <Drawer.Screen name="Home" component={HomePage} />
          <Drawer.Screen name="Generación Recetas" component={RecipeGeneration} />
          <Drawer.Screen name="Mis Recetas" component={UserRecipes} />
      </Drawer.Navigator>
    </NewRecipeGenerationContext.Provider>
  );
}

The thing is, I’m getting this error all the time:

Warning: Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, wrap the container in 'NavigationIndependentTree' explicitly. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them.

But I only have created one NavigationContainer, and it is in the _layout.tsx file!
I don’t understand why it complains that there are more. If someone can tell me why this is so, I would be very grateful.

Neovim JavaScript config

I’m trying to use null-ls with multiple sources for formatting and diagnostics in Neovim. Everything seems to be working fine when I run node file.js/file.ts from the terminal, but when I open the file in Neovim, I always get some issue (not specified in the question).

I’ve configured null-ls and lspconfig for several programming languages (JavaScript, TypeScript, Python, C++, Go, Shell scripts) as shown below, but the problem persists.

Configuration Files:

null-ls.lua:

return {
    {
        'jose-elias-alvarez/null-ls.nvim',
        event = "BufRead",
        dependencies = { 'nvim-lua/plenary.nvim' },
        config = function()
            local null_ls = require('null-ls')

            null_ls.setup({
                sources = {
                    -- JavaScript/TypeScript
                    null_ls.builtins.formatting.prettier.with({ command = "/opt/homebrew/bin/prettier" }), -- Specify Prettier path
                    null_ls.builtins.formatting.eslint_d,
                    null_ls.builtins.diagnostics.eslint_d,
                    null_ls.builtins.code_actions.eslint_d,

                    -- Python
                    null_ls.builtins.formatting.black,
                    null_ls.builtins.formatting.isort,
                    null_ls.builtins.diagnostics.flake8,
                    null_ls.builtins.diagnostics.mypy,

                    -- C/C++
                    null_ls.builtins.formatting.clang_format,
                    null_ls.builtins.diagnostics.cppcheck,

                    -- Go
                    null_ls.builtins.formatting.gofmt,
                    null_ls.builtins.formatting.goimports,
                    null_ls.builtins.diagnostics.golangci_lint,

                    -- Shell scripts
                    null_ls.builtins.formatting.shfmt,
                    null_ls.builtins.diagnostics.shellcheck
                },

                on_attach = function(client, bufnr)
                    if client.name == "null-ls" then
                        vim.api.nvim_buf_set_option(bufnr, "formatexpr", "v:lua.vim.lsp.formatexpr()")
                    end
                end,

                settings = {
                    ["null-ls"] = {
                        setup = {
                            formatting = {
                                prettier = {
                                    tab_width = 2,
                                    single_quote = true,
                                    trailing_comma = "es5"
                                }
                            }
                        }
                    }
                }
            })

            -- Keymap for formatting with null-ls
            vim.keymap.set('n', '<leader>gf', function() vim.lsp.buf.format() end, { noremap = true, silent = true })
        end
    }
}

lsp-config.lua:

return {
    {
        "williamboman/mason.nvim",
        config = function()
            require("mason").setup({
                ui = {
                    border = "rounded",
                    icons = {
                        package_installed = "✓",
                        package_pending = "➜",
                        package_uninstalled = "✗"
                    }
                }
            })
        end
    },
    {
        "williamboman/mason-lspconfig.nvim",
        config = function()
            require("mason-lspconfig").setup({
                ensure_installed = {
                    "clangd",
                    "lua_ls",
                    "gopls",
                    "pyright",
                    "ts_ls" -- Use ts_ls instead of tsserver
                },
                automatic_installation = true
            })
        end
    },
    {
        "neovim/nvim-lspconfig",
        config = function()
            local lspconfig = require("lspconfig")

            -- Global LSP settings
            vim.diagnostic.config({
                virtual_text = true,
                signs = true,
                update_in_insert = false,
                underline = true,
                severity_sort = true,
                float = {
                    border = 'rounded',
                    source = 'always'
                }
            })

            -- Grammarly specific setup with error handling
            local grammarly_ok, _ = pcall(function()
                lspconfig.grammarly.setup({
                    cmd = { "grammarly-languageserver", "--stdio" },
                    filetypes = {
                        "markdown",
                        "text",
                        "tex",
                        "latex"
                    },
                    root_dir = function()
                        return vim.loop.cwd()
                    end,
                    init_options = {
                        clientId = "client_BaDkMgx4X19X9UxxYRCXZo"
                    },
                    settings = {
                        grammarly = {
                            autoActivate = true,
                            suggestions = {
                                writing_style = "default",
                                dialect = "american"
                            }
                        }
                    }
                })
            end)

            if not grammarly_ok then
                vim.notify("Failed to setup Grammarly LSP", vim.log.levels.ERROR)
            end

            -- Setup other LSP servers
            lspconfig.lua_ls.setup({})
            lspconfig.clangd.setup({})
            lspconfig.gopls.setup({})
            lspconfig.pyright.setup({})
            lspconfig.ts_ls.setup({})

            -- Key mappings
            vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, { desc = "Code Action" })
            vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { desc = "Go to Definition" })
            vim.keymap.set('n', 'K', vim.lsp.buf.hover, { desc = "Hover Information" })
            vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, { desc = "Go to Implementation" })
            vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, { desc = "Rename" })
        end
    }
}

I have made sure that all required binaries (Prettier, ESLint, etc.) are properly installed. I’ve also checked both null-ls and lspconfig configurations, but the issue still persists.

Inconsistent pointer lock behavior across browsers

Here is a demo from MDN showing the Pointer Lock API. If you open that in Google Chrome, you’ll notice that the cursor in Chrome moves much faster than in other browsers.

I manually tested Chrome/Firefox/Safari/Edge on all desktop platforms, and found that Windows is the only platform where the browsers all behave the same. On Mac and Linux, Chrome’s mouse movement is too fast.

I thought the issue might be due to acceleration per this article, however the unadjustedMovement: true flag doesn’t make it behave like other browsers. On the contrary, in my testing it seems to make it move even faster than the OS cursor on Macos. Disabling acceleration at the OS level also does not fix it.

Clearly this is a browser bug (in Chrome or in the rest, idk), but are there any existing solutions or workarounds to this problem? Any app/game today that locks the pointer will be way too slow on non-Chrome browsers by default. A user-agent based hack might work, although achieving perfect 1:1 consistency might be difficult.

Why won’t my Tooltip display the data that aligns with the x-axis?

I am currently trying to create a Line Chart using d3. I am having an issue with the tooltip I created. It currently displays data that does not properly align with the x-axis. It currently displays the data for the previous year, rather than the year the user hovers over on the line chart. I have attached a screenshot so you can understand the issue. The code is also attached below. Screenshot: https://i.sstatic.net/kZ3I4eib.png

Here is the code:

// Set up SVG dimensions and margins
const margin = {top: 30, right: 60, bottom: 60, left: 60},
      width = 650 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

const svg = d3.select("#container").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", `translate(${margin.left},${margin.top})`);


// Append the tooltip to the body
const lineTip = d3.select("body")
  .append("div")
  .attr("class", "tooltip")
  .style("position", "absolute")
  .style("padding", "8px")
  .style("background", "rgba(0, 0, 0, 0.7)")
  .style("color", "white")
  .style("border-radius", "4px")
  .style("pointer-events", "none") 
  .style("opacity", 0);

d3.csv("data/overall_arrests.csv").then(data => {
  data.forEach(d => {
    d.arrest_year = new Date (d.arrest_year);  
    d.total_arrests = +d.total_arrests;         
  });
    const x = d3.scaleTime()
    .domain([d3.min(data, d => d.arrest_year), new Date(2024, 0, 1)])
    .range([0, width]);

    const y = d3.scaleLinear()
        .domain([0, d3.max(data, d => d.total_arrests)])
        .range([height, 0]);

    // SVG x-axis
    svg.append("g")
        .attr("transform", `translate(0,${height})`)
        .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%Y")));

    // SVG y-axis
    svg.append("g")
    .call(d3.axisLeft(y));

    // Add X grid lines
    const xAxisGrid = d3.axisBottom(x)
    .tickSize(-height) 
    .tickFormat("")     

    svg.append("g")
    .attr("class", "x grid")
    .attr("transform", `translate(0,${height})`)
    .call(xAxisGrid);

    // Add Y grid lines
    const yAxisGrid = d3.axisLeft(y)
    .tickSize(-width)    
    .tickFormat("") 

    svg.append("g")
    .attr("class", "y grid")
    .call(yAxisGrid);
    
    svg.selectAll(".grid line")
    .style("stroke", "#777")
    .style("stroke-dasharray", "1,1");

    for (let i = 0; i < data.length - 1; i++) {
        svg.append("line")
        .attr("x1", x(data[i].arrest_year))
        .attr("y1", y(data[i].total_arrests))
        .attr("x2", x(data[i + 1].arrest_year))
        .attr("y2", y(data[i + 1].total_arrests))
        .attr("stroke", "darkred")
        .attr("stroke-width", 1.5);
    }
    svg.selectAll("circle")
        .data(data)
        .enter()
        .append("circle")
        .attr("cx", d => x(d.arrest_year))
        .attr("cy", d => y(d.total_arrests))
        .attr("r", 2.5)
        .attr("stroke", "black")
        .attr("fill", "darkred")

    .on("mouseenter", (event, d) => {
      lineTip.transition().duration(200).style("opacity", 0.9);
      lineTip.html(`
        <strong>Year:</strong> ${d.arrest_year.getFullYear()}<br>
        <strong>Total Arrests:</strong> ${d.total_arrests}<br>
      `)
      .style("left", (event.pageX + 10) + "px")
      .style("top", (event.pageY - 28) + "px");
    })
    .on("mousemove", (event) => {
    
      lineTip.style("left", (event.pageX + 10) + "px")
            .style("top", (event.pageY - 28) + "px");
    })
    .on("mouseleave", () => {

      lineTip.transition().duration(200).style("opacity", 0);
    });
        svg.append("text") 
        .attr("transform", "rotate(-90)")
        .attr("y", 0 - margin.left)
        .attr("x", 0 - (height / 2))
        .attr("dy", "1em")
        .style("text-anchor", "middle")
        .style("fill","#777")
        .style("font-size", "14px")
        .text("Not Doxxing Myself");
    
        svg.append("text") 
        .attr("x", width  - 250)
        .attr("x", 330 - margin.left)
        .attr("y", height + margin.top - 345)
        .style("text-anchor", "middle")
        .style("fill","#777")
        .style("font-size", "14px")
        .text("Not Doxxing Myself");

        svg.append("text")
        .attr("x", width - 350)
        .attr("y", height + margin.bottom -24)
        .style("font-size", "12px")
        .style("text-align", "center")
        .style("fill","#777")
        .text("Not Doxxing Myself");

        svg.append("text")
        .style("font-size", "12px")
        .attr("x", width - 325)
        .style("text-align", "center")
        .style("fill","#777")
        .attr("y", height + margin.bottom -8)
        .text("Not Doxxing Myself")

});

accessible comment section / complex list-like environments

We have a widget in our website where people can open a menu and add comments or feedback to a piece of content. Other users can then interact with these comments (like/reply/moderate etc.) That means there is a section inside the webpage that can contain an arbitrary amount of interactive elements, each usually a button or a link.

It is unclear to me how a user with a screen reader would keep up with this. Having tried out NVDA on simply the youtube comment section there seems to be no way to quickly navigate between comments too and TAB simply moves from one “like / dislike / more settings / link to userprofile / add comment” button which means you need to use several inputs to navigate from one comment to the other, which seems assinine to me.

If I would use a controller to navigate such a comment section I would expect that my selection first highlights each individual comment, reading the comment without any context out loud and if I would want to interact with the comment I would “activate / enter” the comment to reveal the user interface regarding that comment alone.

I do not know if this kind of approach would result in an actual accessible comment section or if would break several accessibility guidelines as I would represent simple text sections as interactive elements with there having to be a written guide to what usual actions would result in within this specific context (“Press Enter to interact with this comment. Press ESC to return to the list.”)

Are there best practices to uphold when you are trying to present a section of a webpage with an arbitrary amount of interactive but hierarchically managed elements?

Here is a mockup of the raw structure of this interface.

<div class="menu">
  <div>Feedback</div>
  <div class="comments">
    <ul class="comment-list">
      <li class="comment-item">
        <div class="comment">
          Hello
        </div>
        <button>Like</button>
        <button>Reply</button>
        <button>Remove</button>
      </li>
      <li class="comment-item">
        <div class="comment">
        What
        </div>
        <button>Like</button>
        <button>Reply</button>
        <button>Remove</button>
      </li>
      <li class="comment-item">
        <div class="comment">
        Why
        </div>
        <button>Like</button>
        <button>Reply</button>
        <button>Remove</button>
      </li>
      <li class="comment-item">
        <div class="comment">
        How
        </div>
        <button>Like</button>
        <button>Reply</button>
        <button>Remove</button>        
      </li>
    </ul>
  </div>
  <div class="write-area">
    <textarea placeholder="Write your comment ...">
    </textarea>
    <button type="button" onclick="send"> Send </button>
  </div>
</div>

Open a window, Switch between tabs, close window on browser not working on Playwright Typescript

I’m opening a window (w1) using beforeEach, from that I’m opening another window (w2). Now, I want to perform some actions on (w2) and switch to (w1). And then, close a (w2) window.

  test.beforeEach(async ({ page }) => {
   await page.goto(BASE_URL + "/w1");
  });


test("switch between tabs", async ({ context }) => {

  const page = await context.newPage();

  const [newtab] = await Promise.all([
    context.waitForEvent('page'),    
    await page.goto(BASE_URL + "/w2"),
    await page.getByTestId('id_here').click(),
    await page.getByTestId('id1_here').fill('test')
 ])
 //come back to window (w1)
 //perform actions on window (w1)
 //close window (w2)

});

Error copying 2d array contents to Google Sheets column

In GAS, I have a 2d array that I have populated with data and after the function runs I want to be able to push that data into a single column in a Google Sheet. I keep getting an error that the number of rows in the data doesn’t match the number of rows in the range. Looking for some extra eyes to tell me what I’m doing wrong.

var allExpensesStatus = [];
for (i = 0; i < somevar.length; i++)
{
   allExpensesStatus.push([i,"some text"]);
}

spreadsheet.getSheetByName("MySheet").getRange("H2:H" + allExpensesStatus.length).setValues(allExpensesStatus);

Thank you in advance for your help!

XP P323B printer cannot print text

printer(XP P323B) i correctly print images and barcode but when i print text it prints nothing here is my code in javascript:

import escpos from 'escpos';
import escposUsb from 'escpos-usb';
const device = new escposUsb(0x2D37, 0xCBB4); // Replace with your printer's Vendor ID and Product ID
const options = { encoding: "GB18030" /* default */ }
const printer = new escpos.Printer(device,options);

// Open the device and print a sample text
device.open(() => {
  printer
  
    .text("Hello, World!")
    .cut()
    .close();
});

no text printed but only the printer ejected and prints nothing
i need your help

Prefetching images from AirTable in JavaScript using new Image()

So I have to prefetch images for an application with JavaScript in case the connection drops, the user should still be able to see the images. I’m prefetching a couple hundred images with this function:

// Function to preload a single image
          const preloadImage = (url: string) =>
            new Promise(resolve => {
              const img = new Image();
              img.src = url;
              img.onload = resolve;
              img.onerror = resolve; // Resolve even if an error occurs
            });

but when the app actually gets to displaying the image, it just disregards that I’ve already prefetched these images and tries to do it again and with no connection, it is of course broken.

I also tried batching the image reloads but that also does not work.

When I try only prefetching only one image, it works with some but does not with others.

When I don’t prefetch the images and just go to the section where the images are displayed with great internet connection, the images are shown without a problem so it’s not the url that’s broken.

I’m fetching the images from AirTable by the way, I don’t know if that makes a difference.

how to stop the f5_cspm.wait_perf_data javascript function which is being called recurrently using setTimeout

The f5 loadbalancer is injecting this script to my index page:

<script id="f5_cspm">
(function () {
    var f5_cspm = {
        f5_p: 'someencodedtext',
        
        setCharAt: function (str, index, chr) {
            if (index > str.length - 1) return str;
            return str.substr(0, index) + chr + str.substr(index + 1);
        },
        
        get_byte: function (str, i) {
            var s = (i / 16) | 0;
            i = (i & 15);
            s = s * 32;
            return ((str.charCodeAt(i + 16 + s) - 65) << 4) | (str.charCodeAt(i + s) - 65);
        },
        
        set_byte: function (str, i, b) {
            var s = (i / 16) | 0;
            i = (i & 15);
            s = s * 32;
            str = f5_cspm.setCharAt(str, (i + 16 + s), String.fromCharCode((b >> 4) + 65));
            str = f5_cspm.setCharAt(str, (i + s), String.fromCharCode((b & 15) + 65));
            return str;
        },
        
        set_latency: function (str, latency) {
            latency = latency & 0xffff;
            str = f5_cspm.set_byte(str, 40, (latency >> 8));
            str = f5_cspm.set_byte(str, 41, (latency & 0xff));
            str = f5_cspm.set_byte(str, 35, 2);
            return str;
        },
        
        wait_perf_data: function () {
            try {
                var wp = window.performance.timing;
                if (wp.loadEventEnd > 0) {
                    var res = wp.loadEventEnd - wp.navigationStart;
                    if (res < 60001) {
                        var cookie_val = f5_cspm.set_latency(f5_cspm.f5_p, res);
                        window.document.cookie = 'f5avr0138950615aaaaaaaaaaaaaaaa_cspm_=' + encodeURIComponent(cookie_val) + ';path=/;' + '';
                    }
                    return;
                }
            } catch (err) {
                return;
            }
            setTimeout(f5_cspm.wait_perf_data, 100);
            return;
        },
        
        go: function () {
            var chunk = window.document.cookie.split(/s*;s*/);
            for (var i = 0; i < chunk.length; ++i) {
                var pair = chunk[i].split(/s*=s*/);
                if (pair[0] == 'f5_cspm' && pair[1] == '1234') {
                    var d = new Date();
                    d.setTime(d.getTime() - 1000);
                    window.document.cookie = 'f5_cspm=;expires=' + d.toUTCString() + ';path=/;' + ';';
                    setTimeout(f5_cspm.wait_perf_data, 100);
                }
            }
        }
    };

    f5_cspm.go();
}());
</script>

The reasoning why this is injected is described here: https://my.f5.com/manage/s/article/K13849

After the page loads I would like to use another script or even angular component and remove the <script id=f5_cspm”> and also stop the recurrent call for f5_cspm.wait_perf_data.

I was able to remove the script, but I dont know how to reach the recurent method.
When I try to find it using window.f5_cspm it returns undefined.

import { Injectable, Renderer2, RendererFactory2} from '@angular/core'; 

@Injectable({
    providedIn: 'root'  // This makes the service available globally in the app
})

export class MyService {
    
    private renderer: Renderer2;

    constructor( private rendererFactory: RendererFactory2) { 
        this.renderer = rendererFactory.createRenderer(null, null);
        this.removef5()
    }

    private removef5() {
        console.log('removef5  ');
        
        const scriptTag = document.getElementById("f5_cspm");
        if (scriptTag) {
            console.log("script will be removed: " + scriptTag); 
            this.renderer.removeChild(scriptTag.parentElement, scriptTag);  // Removes the script from the DOM
        }
         console.log('window.f5_cspm  ' + window.f5_cspm); // prints undefined 
    } 
}