Closed ahofmeister closed 1 month ago
I am experiencing similar issues with Advanced Select and other pure JS components. Here's what might be happening:
If anyone can point out a good way to get around this, the Advanced Select and other JS components are amazingly-well designed.
If rendered conditionally, the select is not rendered at all. I have checked the other issues, but could not find any specific related to this topic. If it is a duplicate, please close it :)
'use client'; import React, { useState } from 'react'; const Custom = () => { const [display, setDisplay] = useState(false); return ( <div> <div onClick={() => setDisplay(true)}>display to true</div> {display && ( <div> yes <select data-hs-select='{ "placeholder": "Select option...", "toggleTag": "<button type=\"button\"></button>", "toggleClasses": "hs-select-disabled:pointer-events-none hs-select-disabled:opacity-50 relative py-3 px-4 pe-9 flex text-nowrap w-full cursor-pointer bg-white border border-gray-200 rounded-lg text-start text-sm focus:border-blue-500 focus:ring-blue-500 before:absolute before:inset-0 before:z-[1] dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400", "dropdownClasses": "mt-2 z-50 w-full max-h-72 p-1 space-y-0.5 bg-white border border-gray-200 rounded-lg overflow-hidden overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 dark:[&::-webkit-scrollbar-track]:bg-neutral-700 dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500 dark:bg-neutral-900 dark:border-neutral-700", "optionClasses": "py-2 px-4 w-full text-sm text-gray-800 cursor-pointer hover:bg-gray-100 rounded-lg focus:outline-none focus:bg-gray-100 dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:text-neutral-200 dark:focus:bg-neutral-800", "optionTemplate": "<div class=\"flex justify-between items-center w-full\"><span data-title></span><span class=\"hidden hs-selected:block\"><svg class=\"flex-shrink-0 size-3.5 text-blue-600 dark:text-blue-500\" xmlns=\"http:.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg></span></div>", "extraMarkup": "<div class=\"absolute top-1/2 end-3 -translate-y-1/2\"><svg class=\"flex-shrink-0 size-3.5 text-gray-500 dark:text-neutral-500\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m7 15 5 5 5-5\"/><path d=\"m7 9 5-5 5 5\"/></svg></div>" }' className="hidden" > <option value="">Choose</option> <option>Name</option> <option>Email address</option> <option>Description</option> <option>User ID</option> </select> </div> )} </div> ); }; export default Custom;
I have created https://stackblitz.com/edit/stackblitz-starters-uc54d1 for it.
It seems, that the select is not rendered if the visibility is handled with a state update. It works fine, if the select is put outside of the condition.
Hi,
in your case, the best way to use HSSelect
is to initialize it using a constructor.
'use client';
import React, { useState, useEffect, useRef } from 'react';
import { HSSelect, ISelect, ISelectOptions } from 'preline/preline';
const Custom = () => {
const selectRef = useRef<null | HTMLSelectElement>(null);
const hsSelectRef = useRef<ISelect | null>(null);
const [display, setDisplay] = useState(false);
const [selectVal, setSelectVal] = useState('');
const options: ISelectOptions = {
placeholder: 'Select option...',
dropdownSpace: 10,
value: selectVal,
toggleTag: '<button type="button"></button>',
toggleClasses:
'hs-select-disabled:pointer-events-none hs-select-disabled:opacity-50 relative py-3 px-4 pe-9 flex text-nowrap w-full cursor-pointer bg-white border border-gray-200 rounded-lg text-start text-sm focus:border-blue-500 focus:ring-blue-500 before:absolute before:inset-0 before:z-[1] dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400',
dropdownClasses:
'mt-2 z-50 w-full max-h-72 p-1 space-y-0.5 bg-white border border-gray-200 rounded-lg overflow-hidden overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 dark:[&::-webkit-scrollbar-track]:bg-neutral-700 dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500 dark:bg-neutral-900 dark:border-neutral-700',
optionClasses:
'py-2 px-4 w-full text-sm text-gray-800 cursor-pointer hover:bg-gray-100 rounded-lg focus:outline-none focus:bg-gray-100 dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:text-neutral-200 dark:focus:bg-neutral-800',
optionTemplate:
'<div class="flex justify-between items-center w-full"><span data-title></span><span class="hidden hs-selected:block"><svg class="flex-shrink-0 size-3.5 text-blue-600 dark:text-blue-500" xmlns="http:.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></div>',
extraMarkup:
'<div class="absolute top-1/2 end-3 -translate-y-1/2"><svg class="flex-shrink-0 size-3.5 text-gray-500 dark:text-neutral-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg></div>',
};
useEffect(() => {
if (display && selectRef.current) {
hsSelectRef.current = new HSSelect(selectRef.current, options);
(hsSelectRef.current as HSSelect).value = selectVal;
(hsSelectRef.current as HSSelect).on('change', (payload: string) =>
setSelectVal(payload)
);
return () => {
if (hsSelectRef.current && (hsSelectRef.current as ISelect).destroy) {
(hsSelectRef.current as ISelect).destroy();
hsSelectRef.current = null;
}
};
}
}, [display]);
return (
<div>
<button type="button" onClick={() => setDisplay(!display)}>
Toggle select
</button>
{display && (
<div>
yes
<select
ref={selectRef}
data-hs-select
className="--prevent-on-load-init"
style={{
display: 'none',
}}
>
<option value="">Choose</option>
<option value="name">Name</option>
<option value="emailAddress">Email address</option>
<option value="description">Description</option>
<option value="userId">User ID</option>
</select>
</div>
)}
</div>
);
};
export default Custom;
I've added an example here https://stackblitz.com/edit/stackblitz-starters-nxlqpw
Summary:
Hi @olegpix
I really appreciate your answer and time you put into it! We decided (not only because of this issue) to move forward with another library instead of Preline.
Not sure if you want to have this issue to remain open or not.
@olegpix There's an error in the stackblitz. https://stackblitz.com/edit/stackblitz-starters-uc54d1
ReferenceError: self is not defined
Any notes on how to resolve?
@olegpix There's an error in the stackblitz. https://stackblitz.com/edit/stackblitz-starters-uc54d1
ReferenceError: self is not defined
Any notes on how to resolve?
I solved it this way. But this is not a subject of the opened issue.
import dynamic from 'next/dynamic';
const DynamicCustom = dynamic(() => import('@/components/custom'), {
ssr: false,
});
export default function Home() {
return (
<main className="flex min-h-screen flex-col">
<DynamicCustom />
</main>
);
}
The same happens when used in Angular and I suspect a similar reason as in Next.js. You have to call window.HSStaticMethods.autoInit(['select']);
to make it work again.
The same happens when used in Angular and I suspect a similar reason as in Next.js. You have to call
window.HSStaticMethods.autoInit(['select']);
to make it work again.
@Gordi90 provide the vivid hint. Just use autoInit();
useEffect(() => {
const loadPreline = async () => {
await import("preline/preline");
window.HSStaticMethods.autoInit();
};
loadPreline();
}, [isLoaded]);
If rendered conditionally, the select is not rendered at all. I have checked the other issues, but could not find any specific related to this topic. If it is a duplicate, please close it :)
I have created https://stackblitz.com/edit/stackblitz-starters-uc54d1 for it.
It seems, that the select is not rendered if the visibility is handled with a state update. It works fine, if the select is put outside of the condition.