Window.open() forgets previous window name after reload/postback

I am facing an issue with chrome for a single user where window.open() in js does not remembers the window name and creates another window when page posts back(razor pages c#). This issue does not occur with any other user or other browser for the same user. Is there a chrome flag or setting that affects its behaviour.

I checked the popup settings and they were fine. It works fine on other browsers (Edge). Issue is only on chrome. Manually, running window.open in the browser remembers window name before page refresh but forgets and opens another popup with the same name if page is refreshed.

How do you update an existing CSSStyleSheet

I’m using new CSSStyleSheet() to create a custom stylesheet for a specific document where the styles depend on the content.
Within that stylesheet, I add CSS variables with the root selector. Elements in the project will then be selected by an ID and get specific rules that use those variables. The issue is, that I do not know the IDs before, and as such the styles and the selectors have to be created dynamically.
So far it works flawlessly.

The issue that I facing now is that during some specific events, the value of the CSS variables should change. I tried changing it by using insertRule() with and without index. I also tried replace() and replaceSync(). Nothing achieved the desired result.

The question now is, how can I change the root for this stylesheet?

const CSS = new CSSStyleSheet();

const rootRule = `:root{
  --background: red;
}`;
CSS.insertRule(rootRule, 0);

const bodyRule = `body { 
  background: var(--background); 
}`
CSS.insertRule(bodyRule, 1);

document.adoptedStyleSheets = [CSS];


// change color
BUTTON.addEventListener('click', function() {
  console.log('button clicked');
  const newRule = `:root {
    --background: blue;
  }`
  CSS.insertRule(newRule, 0);
})
<button id="BUTTON">Change background-color</button>

Node React connection

Is there a way to connect react and node? I found out how to connect express with node but I can’t find how it works with react. Every video in the internet shows different ways but they don’t work, can someone help please?

I tried many methods trying to connect them but none work, also if they connect how can i pass values for example from an input type=”text” in react to a function that works in node

FastAPI and HTML

I’m trying to embed a sidebar in several HTML files, but I’m not succeeding. I’m using FastAPI, HTML, CSS and JS. Here is the template of what I’m trying to do, but only getting 404 not found for sidebar.html.

Here is the login.py:

from fastapi import FastAPI, APIRouter, Form, Depends, Request
from fastapi.responses import RedirectResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from starlette import status
import os

from app.services.login import Login
from app.db.conn import users
from app.utils.cookie_auth import get_user_hash_from_auth_cookie, remove_auth, set_auth

app = FastAPI()

# Montando arquivos estáticos
app.mount("/static", StaticFiles(directory="app/static"), name="static")
app.mount("/template", StaticFiles(directory="app/template", html = True), name="template")

router = APIRouter()

@router.get("/", response_class=HTMLResponse)
async def main_page(request: Request):
    if get_user_hash_from_auth_cookie(request):
        return RedirectResponse(url="/home")
    else:
        with open("app/template/html/login.html") as f:
            content = f.read().replace("{{ error_message }}", "")
            return HTMLResponse(content=content)


@router.get("/login", response_class=HTMLResponse)
async def login_form(request: Request):
    with open("app/template/html/login.html") as f:
        content = f.read().replace("{{ error_message }}", "")
        return HTMLResponse(content=content)


@router.post("/login")
async def login(request: Request, username: str = Form(...), password: str = Form(...), db=Depends(users)):
    service = Login(request, db)
    try:
        user = service.get_user(username)

        if user["password"] == password:
            response = RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
            set_auth(response, username, user["privilages"])
            return response
        else:
            # Exibir erro de senha incorreta
            with open("app/template/html/login.html") as f:
                content = f.read().replace("{{ error_message }}", "Senha incorreta")
                return HTMLResponse(content=content)
    except Exception as e:
        print(e)
        # Exibir erro de usuário não encontrado
        with open("app/template/html/login.html") as f:
            content = f.read().replace("{{ error_message }}", "Usuário não encontrado")
            return HTMLResponse(content=content)


@router.get("/home", response_class=HTMLResponse)
async def home(request: Request):
    if not get_user_hash_from_auth_cookie(request):
        return RedirectResponse(url="/login", status_code=status.HTTP_302_FOUND)

    with open("app/template/html/home.html") as f:
        return HTMLResponse(content=f.read())


@router.get("/logout")
async def logout():
    response = RedirectResponse(url="/login", status_code=status.HTTP_302_FOUND)
    remove_auth(response)
    return response

app.include_router(router)

Here is the sidebar.html:

<!-- sidebar.html -->
<div class="sidebar">
    <div class="sidebar-header">
        <img src="/static/images/logo.png" alt="Logo" class="logo">
    </div>
    <ul class="sidebar-menu">
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-home"></i> Painel
            </a>
        </li>
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-envelope"></i> Mensagens
            </a>
        </li>
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-search"></i> Pesquisas
            </a>
        </li>
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-paper-plane"></i> Disparos
            </a>
        </li>
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-check-square"></i> Auditoria
            </a>
        </li>
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-shopping-cart"></i> Vendas
            </a>
        </li>
        <li class="menu-item">
            <a href="#">
                <i class="fas fa-exchange-alt"></i> Negociações
            </a>
        </li>
    </ul>
</div>

Here is home.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Painel SCC - Home</title>
    <link rel="stylesheet" href="/static/css/home.css">
    <link rel="stylesheet" href="/static/css/sidebar.css">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta2/css/all.min.css" rel="stylesheet">
</head>
<body>
    <div id="sidebar-placeholder"></div>
    <div class="content">
        <!-- Seu conteúdo principal vai aqui -->
    </div>

    <!-- Importando o arquivo JavaScript -->
    <script src="/static/js/sidebar.js"></script>
</body>
</html>

Here is sidebar.js:

document.addEventListener("DOMContentLoaded", function() {
    fetch('/template/html/sidebar.html')
    .then(response => response.text())
    .then(data => {
        document.getElementById('sidebar-placeholder').innerHTML = data;
    });

});

Boolean property is required

I have a custom Form element, the type of it requires a multipart argument, when it passes, the form will be a FormData form, if is not, it will be a JSON form, and I want to do it this way:

<CustomForm<DataFields> ...arguments>  (JSON FORM)
    ...
</CustomForm>

<CustomForm<DataFields> multipart ...arguments>  (MULTIPART FORM)
    ...
</CustomForm>

but it actually shows an typing error when I do the first one (JSON form), instead, I need to do this:

<CustomForm<DataFields> multipart={false} ...arguments>  (JSON FORM)
    ...
</CustomForm>

This is the error I get:

Type '{ children: Element[]; onSubmit: () => void; }' is not assignable to type 'IntrinsicAttributes & CustomFormProps<FieldValues>'.
  Property 'multipart' is missing in type '{ children: Element[]; onSubmit: () => void; }' but required in type '{ multipart: false | void | null | undefined; onSubmit: (data: FieldValues) => void; }'.ts(2322)
form.ts(12, 2): 'multipart' is declared here.

At first, this is what my Type looked like:

type CustomFormProps<T extends any> = {
    children?: ReactNode | ReactNode[]
    setMethods?: Function
    className?: string
} & ({
    multipart: true
    onSubmit: (data: FormData) => void
} | {
    multipart: false
    onSubmit: (data: T) => void
})

Then I though, “ok, it must be because when I don’t pass any value, the multipart property gets an ‘undefined'” so I changed it to this:

type CustomFormProps<T extends any> = {
    children?: ReactNode | ReactNode[]
    setMethods?: Function
    className?: string
} & ({
    multipart: true
    onSubmit: (data: FormData) => void
} | {
    multipart: false | undefined | null | void
    onSubmit: (data: T) => void
})

But it didn’t work either. What do I need to do to fix this?

I’m using Redis with MySQL in a Node.js webite but my data changes frequently. Is Redis caching a good idea in this case?

I implemented the middleware that expires in 5 minutes, but how will the cache update? I also tried another approach with Pub/Sub using Redis, but when will it update? In the update function, I also tried something like this:

But this will I want to add everywhere when db is inserted, delted,updated then delete the cache key. Any other solution for this?

Redis implementation logic with better solution how to delete a cache when update delete insert in primary DB.

How to search data inside two different array and copy the matching data into new array in Angular 8

I have array1 and array2 in below data.i wanted to iterate all factoryId of array1 and need to check if same factoryid is present in array2.

if factoryId of array1 is matching with array2 factoryId , than i wanted to prepare new result array with array1 object and status field from array2 into new result array.

Expected output is a combination of array1 and array2 status field.

can anyone help me to do this

const array1 = [
    {
        "name": "Africa",
        "filterChildren": [
            [
                {
                    "name": "Agbara - Laundry",                  
                    "factoryId": "R_X001"                  
                },
                {
                    "name": "Agbara - Savoury",
                    "factoryId": "R_X002"
                }               
            ]
        ]
    },
    {
        "name": "X-Ekaterra",
        "filterChildren": [
            [
                {
                    "name": "Agbara - Tea",
                    "factoryId": "R_x903"                   
                }
            ]
        ]
    }
];


const array2 = [
    {
        "FactoryId": "R_X001",
        "Status": "Draft"
    },
    {       
        "FactoryId": "R_x903",
        "Status": "Submitted"
    }
]

Expected Output

Expected Result = [
    {
        "name": "Africa",
        "filterChildren": [
            [
                {
                    "name": "Agbara - Laundry",                  
                    "factoryId": "R_X001",
                    "Status": "Draft"
                },
                {
                    "name": "Agbara - Savoury",
                    "factoryId": "R_X002"
                }               
            ]
        ]
    },
    {
        "name": "X-Ekaterra",
        "filterChildren": [
            [
                {
                    "name": "Agbara - Tea",
                    "factoryId": "R_x903",
                    "Status": "Submitted"                  
                }
            ]
        ]
    }
];

Can “new Function()” be safe?

I understand that it’s risky to consider this when it comes to security. However I am currently planning a project with the following ambitions:

Create a grammar using Nearley.js.

Use that grammar to store a function in my database for example:

"IF(G.cells[id]!=NULL){INVALIDMOVE}, playerID->G.cells[id]"

That function gets translated in the following parser in the following way:

function translateAST(ast) {
  switch (ast.type) {
    case 'condition':
      return `
        if (${translateExpr(ast.condition)}) {
          return ${translateAction(ast.action)};
        }
      `;
    case 'assignment':
      return `
        ${ast.target} = ${translateExpr(ast.value)};
      `;
    default:
      throw new Error(`Unknown AST node type: ${ast.type}`);
  }
}

function translateExpr(expr) {
  switch (expr.type) {
    case 'notEqual':
      return `${expr.left} !== ${expr.right}`;
    case 'identifier':
      return expr.name;
    default:
      throw new Error(`Unknown expression type: ${expr.type}`);
  }
}

function translateAction(action) {
  switch (action.type) {
    case 'action':
      if (action.name === 'INVALID_MOVE') {
        return 'INVALID_MOVE';
      }
    default:
      throw new Error(`Unknown action type: ${action.type}`);
  }
}

Then after we have parsed this

function generateMoveFunction(code) {
  return function({ G, playerID }, id) {
    // Use a closure to safely execute the code
    const func = new Function('G', 'playerID', 'id', `
      ${code}
    `);
    return func(G, playerID, id);
  };
}


// Example usage
const moveString = "IF(G.cells[id]!=NULL){INVALIDMOVE}, playerID->G.cells[id]";
const ast = parseMove(moveString);
const code = translateAST(ast);
const moveFunction = generateMoveFunction(code);

Then pass this moveFunction as a move for a library

const moves = {
  clickCell: moveFunction,
};

// Boardgame.io game configuration
const MyGame = {
  setup: () => ({ cells: Array(9).fill(null) }),
  moves: moves,
};

Is this a bad idea?

Async await, returning undefined

I am trying to get an ID then use that id in another function, I get the error:

There has been a problem with your fetch operation: undefined

getPreferences()
  .then((id) => updatePreferences(id))
  .then(() => console.log('Success'))
  .catch(function (error) {
    console.log(
      'There has been a problem with your fetch operation: ' +
        error.message,
    );
    throw error;
  });

Async functions:

export const getPreferences = async () => {
  try {
    const response = await get(API_GET_PREFERENCES, null, null);
    return response;
  } catch (e) {
    logCustomException('Error getting preferences id', e);
    throw e;
  }
};


export const updatePreferences = async (id) => {
  try {

    const response = await put(API_UPDATE_PREFERENCES, null, id, null, false);

    return response;
  } catch (e) {
    logCustomException('Error getting preferences id', e);
    throw e;
  }
};

Create a dynamic dictionary in apps script google sheet

I have a column with data in google sheets like this:

col_name
A
A
A
B
B
C

I want to store this data in a dictionary where column value is a key and number of occurrences is a value:

dict = {A:3, B:2, C:1}

I tried to iterate through a list of values:

col_values = mySheet.getRange(2, col, last_row-1, 1).getValues();

With a function:

function count_occurances_in_col(col_values){
  let occurances_dict = new Map();
  for(var i=0;i<=col_values.length;i++){
    if(occurances_dict.has(col_values[i][0])){
      let value = occurances_dict.get(col_values[i][0]);
      occurances_dict.set(col_values[i][0], value+1);
    } else {
      occurances_dict.set(col_values[i][0], 1);
    }
  }
  return occurances_dict;
};

But the function returns undefined instead of a dictionary (perhaps) because keys are set dynamically (if I understood correctly the forums – I don’t know JS well, only python).

Can I obtain such a dict with some function or any other way?

Notice that getValues() method returns col_values in a form:

[[A], [A], [A], [B], [B], [C]]

How to do undo and redo functionality in webxr by using aframe

<title>A-Frame Undo/Redo/Delete Example</title>



<style>

    .ui-button {

        position: absolute;

        padding: 10px 20px;

        background: #333;

        color: #fff;

        border: none;

        cursor: pointer;

        font-size: 18px;

    }

    .ui-button:hover {

        background: #555;

    }

    #delete-button {

        top: 20px;

        left: 20px;

    }

    #undo-button {

        top: 20px;

        left: 100px;

    }

    #redo-button {

        top: 20px;

        left: 180px;

    }

</style>



<a-scene progressive-controls>

    <a-asset-item id="anotherchair" src="https://cdn.glitch.global/3c9342e0-0b69-45d0-b7e8-6f2e8cb53f2c/Chair.glb?v=1719489270451"></a-asset-item>

    <a-asset-item id="chair" src="https://cdn.glitch.global/3c9342e0-0b69-45d0-b7e8-6f2e8cb53f2c/Chair.glb?v=1719489270451"></a-asset-item>

    <a-asset-item id="sofa" src="https://cdn.glitch.global/3c9342e0-0b69-45d0-b7e8-6f2e8cb53f2c/Sofa.glb?v=1719489265917"></a-asset-item>

    <a-entity gltf-model="#anotherchair" class="clickable" position="-4 1 -3" grabbable></a-entity>

    <a-entity gltf-model="#chair" class="clickable" position="-2 1 -3" grabbable></a-entity>

    <a-entity gltf-model="#sofa" class="clickable" position="-6 1 -3" grabbable></a-entity>

    <a-camera position="0 1.6 0">

        <a-cursor></a-cursor>

    </a-camera>

</a-scene>

<button id="delete-button" class="ui-button">Delete</button>

<button id="undo-button" class="ui-button">Undo</button>

<button id="redo-button" class="ui-button">Redo</button>

<script>




    let actionHistory = [];
    let redoStack = [];
    let selectedEntity = null;
    const scene = document.querySelector('a-scene');

    // Serialize entity data including all necessary attributes

   

    function serializeEntity(entity) {
        const attributes = {};
        ['position', 'rotation'].forEach(attr => {
            const value = entity.getAttribute(attr);
            if (value) {
                attributes[attr] = value;
            }
        });

        return {
            id: entity.getAttribute('id'),
            type: entity.tagName.toLowerCase(),
            attributes: attributes
        };

    }

    // Create an entity from serialized data

    function createEntityFromData(data) {

        const entity = document.createElement(data.type);

        entity.setAttribute('id', data.id);

        Object.keys(data.attributes).forEach(attr => {

            entity.setAttribute(attr, data.attributes[attr]);

        });

        return entity;

    }

    // Handle deletion and store the state for undo

    function deleteEntity(entity) {

        const data = serializeEntity(entity);
        //data = position, rotation of entity add

        actionHistory.push({ action: 'delete', data: data });

        redoStack = []; // Clear redo stack on new action

        entity.parentNode.removeChild(entity);

        selectedEntity = null; // Clear selected entity after deletion

    }

    // Handle undo operation

    function undo() {

        if (actionHistory.length === 0) return;

        const lastAction = actionHistory.pop();

        redoStack.push(lastAction);

        if (lastAction.action === 'delete') {

            const restoredEntity = createEntityFromData(lastAction.data);

            scene.appendChild(restoredEntity);
            //restoreEntity . position, rotation

            restoredEntity.addEventListener('click', () => selectEntity(restoredEntity));

        }

    }

    // Handle redo operation

    function redo() {

        if (redoStack.length === 0) return;

        const lastRedo = redoStack.pop();

        actionHistory.push(lastRedo);

        if (lastRedo.action === 'delete') {

            const entity = scene.querySelector( lastRedo.data.id);

            if (entity) {

                entity.parentNode.removeChild(entity);

            }

        }

    }

    // Select an entity

    function selectEntity(entity) {

        selectedEntity = entity;

    }

    // Attach click event to all clickable entities

    document.querySelectorAll('.clickable').forEach((entity) => {

        entity.addEventListener('click', () => selectEntity(entity));

    });

    // Bind UI buttons for delete, undo, and redo

    document.getElementById('delete-button').addEventListener('click', () => {

        if (selectedEntity) deleteEntity(selectedEntity);

    });

    document.getElementById('undo-button').addEventListener('click', undo);

    document.getElementById('redo-button').addEventListener('click', redo);


</script>

Here is the code what i have tried and deleting is working fine but when i am clicking on undo it is placing at some other place.

I want to place the object at initial plosition

Initial Image before delete and undo

after deleting and undoing it is placing in different position

I need to fix this issue

I am working on webxr for learning i need to add undo and redo functionality so anyone please help me to fix it.

it is placing in differenct position from initial position it placing at position= {0, 0 ,0}, and rotation= {0, 0 ,0}

BEFORE RUNNING ABOVE FILE
PLEASE ADD THESE SCRIPTS IN HEAD TAG

GET request to `getOne` controller. Postman returns no data from MongoDB and causes endless request loop

sample data and postman req image I am sending “get” request on Postman. Unfortunately, there is no luck and I can’t find the mistake. Here is my factory.js :

exports.getOne = (Model, popOptions) =>
  catchAsync(async (req, res, next) => {
    console.log('GET ONE');
    let query = Model.findById(req.params.id);
    if (popOptions) query = query.populate(popOptions);
    const doc = await query;
    if (!doc) {
      return next(
        new AppError('No documents fond with that id', 404)
      );
    }
    res.status(200).json({
      status: 'success',
      data: {
        data: doc,
      },
    });
  });

controller :

exports.getTourById = factory.getOne(Tour, { path: 'reviews' });

I tried to change controller and at the end no luck ana here is sample data in my DB.

Using React, how should I fetch data from an API so I can display it on Chart.js charts?

I am quite new to this so I hope my question makes sense.
I am trying to build a React app that allows users to input values and then return charts showing data from an API. Here is a simple explanation of how it should work using a weather forecast as an example:
The user chooses the day, hour, and location and submits the form.
These values are inserted into a URL that returns a JSON with the amount of rain expected for that time and place.
The user sees a Chart.js chart showing the amount of rain expected.

I have made some attempts and I have been able to fetch the data using Axios, but I am unable to make it work with the charts, also I feel that my work is not well structured and I would appreciate an overview of how this could best be done.

I fetched the data using axios and tried to assign the values in the data to variables that the charts will display. However, if I do this then the charts won’t show up at all, it seems I’m far from the correct solution.

how to fix the alignment of the comment’s Text?

I want to put the comment’s text underneath the user image like this layout:enter image description here

this is the current html:

                                        <div class="custom-box">
                                            <div class="comments-container">
                                                <div
                                                    class="dropdown-container p"
                                                    onclick="toggleDropdown()"
                                                >
                                                    <span class="mt-1"
                                                        >التعليقات</span
                                                    >
                                                    <span class="arrow mt-1"></span>
                                                </div>
                                                <div
                                                    id="dropdownContent"
                                                    class="dropdown-content"
                                                >
                                                    <h3>إضافة تعليق</h3>
                                                    <div
                                                        class="comment-input-container"
                                                    >
                                                        <input
                                                            type="text"
                                                            id="commentText"
                                                            class="comment-input"
                                                        />
                                                    </div>
                                                    <button
                                                        onclick="addComment()"
                                                        class="add-comment-button"
                                                    >
                                                        أضف
                                                    </button>
                                                    <div id="commentsList"></div>
                                                </div>
                                            </div>
                                        </div>

and this is the styling:

.comments-container {
    padding-bottom: 0px !important;

    .dropdown-container {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px 20px;
        border-radius: 8px;
        margin-bottom: 20px;
        cursor: pointer;
        font-weight: 900;
    }

    .dropdown-container:hover {
        opacity: 0.8;
    }

    .dropdown-container .arrow {
        padding: 15px;
        border-radius: 3px;
        height: 50px;
        color: black;
        padding-right: 30px;
        font-size: 14px;
        position: relative;
        -moz-appearance: none;
        -webkit-appearance: none;
        appearance: none;
        border: none;
        background: url("data:image/svg+xml;utf8,<svg viewBox='0 0 140 140' width='24' height='24' xmlns='http://www.w3.org/2000/svg'><g><path d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='black'/></g></svg>")
            no-repeat;
        background-position: right 5px top 50%;
    }

    .dropdown-content {
        display: none;
        padding: 20px;
        border-radius: 8px;
        margin-top: 10px;
    }

    .dropdown-content.show {
        display: block;
    }

    .comment-card {
        display: flex;
        flex-direction: row;
        align-items: flex-start;
        background-color: white;
        padding: 10px;
        border-radius: 15px;
        margin-top: 10px;
        margin-left: 10px;
        border: 1px solid #ddd;
    }

    .comment-card img {
        border-radius: 50%;
        width: 40px;
        height: 40px;
        margin-left: 10px;
    }

    .comment-content {
        display: flex;
        flex-direction: column;
        flex-grow: 1;
    }

    .comment-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        width: 100%;
        padding-left: 10px;
    }

    .comment-header .user-name {
        font-size: 14px;
        font-weight: 900;
        color: #000;
    }

    .comment-header .comment-date {
        font-size: 12px;
        color: #888;
    }

    .comment-text {
        margin-top: 5px;
        font-size: 16px;
        padding-left: 10px;
    }

    .add-comment-button {
        padding: 10px 20px;
        background-color: #0056b3;
        color: white;
        border: none;
        border-radius: 35px;
        width: 150px;
        height: 42px;
        cursor: pointer;
        margin-top: 20px;
        margin-left: 10px;
    }

    .add-comment-button:hover {
        background-color: #004494;
    }

    .comment-input-container {
        display: flex;
        align-items: center;
        margin-top: 10px;
    }

    .comment-input {
        flex-grow: 1;
        border-radius: 10px;
        border: 1px solid #ddd;
        padding: 10px;
        margin-left: 10px;
        height: 60px;
    }
}

and the javascript :

            <script>
document.addEventListener("DOMContentLoaded", function () {
    addDefaultComment(); // Add a default comment when the page loads
    keepDropdownOpen();  // Keep the dropdown open by default
});

function toggleDropdown() {
    const dropdownContent = document.getElementById("dropdownContent");
    dropdownContent.classList.toggle("show");
}

function keepDropdownOpen() {
    const dropdownContent = document.getElementById("dropdownContent");
    dropdownContent.classList.add("show"); // Keep the dropdown open by default
}

function addComment() {
    const commentText = document.getElementById("commentText").value;
    if (commentText.trim() === "") return;

    createCommentElement(commentText, "زائر"); // Replace "زائر" with actual user name if available

    document.getElementById("commentText").value = "";
}

function createCommentElement(commentText, userName) {
    const commentList = document.getElementById("commentsList");
    const newComment = document.createElement("div");
    newComment.classList.add("comment-card");

    const userImage = document.createElement("img");
    userImage.src = "https://via.placeholder.com/40"; // Placeholder image
    newComment.appendChild(userImage);

    const commentContent = document.createElement("div");
    commentContent.classList.add("comment-content");

    const commentHeader = document.createElement("div");
    commentHeader.classList.add("comment-header");

    const userNameElement = document.createElement("span");
    userNameElement.classList.add("user-name");
    userNameElement.innerText = userName;
    commentHeader.appendChild(userNameElement);

    const commentDate = document.createElement("span");
    commentDate.classList.add("comment-date");
    const date = new Date();
    commentDate.innerText = `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
    commentHeader.appendChild(commentDate);

    commentContent.appendChild(commentHeader);

    // Add a line break after the comment header
    const lineBreak = document.createElement("br");
    commentContent.appendChild(lineBreak);

    const commentTextElement = document.createElement("div");
    commentTextElement.classList.add("comment-text");
    commentTextElement.innerText = commentText;

    commentContent.appendChild(commentTextElement);
    newComment.appendChild(commentContent);

    commentList.appendChild(newComment);
}


function addDefaultComment() {
    const defaultCommentText = "هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!هنا يجب أن يكون التعليق!";
    createCommentElement(defaultCommentText, "زائر"); 
}

document.getElementById("commentText").addEventListener("keypress", function (event) {
    if (event.key === "Enter") {
        event.preventDefault(); // Prevents the default action of the Enter key
        addComment();
    }
});

            </script>

what should I do to get the required output like the image?

the comment’s text should start underneath the user image , my output is showing the comment’s text next to it not underneath it , what is the problem? or what did I miss? please point me to the right approach

Importing vs Rendering of custom Web Components in Angular

We are building a native JS web component library (Foo Web Components, or FWC), and we are trying to use it in an Angular application (for now, without a wrapper).

  • We are packing it as an NPM package, and installing it as a dependency through npm i @foo/foo-web-components.
  • We are importing the necessary components in a brand new Angular 18 application in a module.
  • We are attempting to use two components (Input and Datepicker) in a simple app.component.

Our relevant files now look as follow:

app.component.ts:

import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, ViewChild } from '@angular/core';

import { FWCInput, FWCDatepicker } from '@foo/foo-web-components';

@Component({
  selector: 'app-root',
  standalone: true,
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppComponent {
  public today: Date = new Date();
  //@ts-ignore
  @ViewChild("datepicker") datepicker: ElementRef<FWCDatepicker>;
  //@ts-ignore
  @ViewChild("input") input: ElementRef<FWCInput>;

  constructor() { }

  ngAfterViewInit(): void {
    console.log(this.datepicker);
    console.log(this.input);
  }
}

app.component.html:

Datepicker: <fwc-datepicker #datepicker [date]="today" label="Datepicker"></fwc-datepicker>
Input: <fwc-input #input placeholder="placeholder" value="From Template" label="Input"></fwc-input>

With this configuration, the page looks like this:
not-working
No errors in the console or build process, but the components aren’t in the DOM or rendered.

However, if we add a single line in the constructor of the app.component.ts as so:

  constructor() {
    var foo = new FWCInput();
  }

Suddenly the components appear:
working

I’m assuming it’s got to do with something related to when Angular actually loads an import… If it’s “not actually used” (as perceived by the framework) it won’t load it.
However, when we import just ONE of the members from the library (in this case, the FWCInput), the whole library gets pulled-in and everything works (including the FWCDatepicker which wasn’t referenced in a new variable).

Why is this, and how would we go about as library designers to allow users to just “use” our components without instantiating disposable variables?

EDIT: Removed the fwc.module.ts file since it wasn’t needed (came from previous tests…).