#how to reference dynamically changing amount of elements

25 messages · Page 1 of 1 (latest)

mellow turret
#

in the docs it is described to use a signal, to get the ref of an element, for example:

const mySignal = useSignal(0);

<article ref={myRef} />

but i am rendering several elements from an array, and wanted to get the reference of each element. how would i go about it, with the correct typing?

i tried using useStore and the key being the ID of the element. i have passed the ref down to the native element, but i get the following error:

Type 'HTMLDialogElement' is not assignable to type 'Ref<T> | undefined'.ts(2322)
jsx-runtime.d.ts(1367, 5): The expected type comes from property 'ref' which is declared here on type 'DialogHTMLAttributes<HTMLDialogElement>'

and here it is being assigned:

  const dialogRefs = useStore<DialogRefs>({});


                  <TalkModal
                    {...usableData}
                    ref={(el) => {
                      if (el) {
                        dialogRefs[talk.id] = el;
                      }
                    }}
                  />

which is incorrect.

outer plaza
mellow turret
#

I have aqn array, for example:

#
const arr = [{id: 1, title: "alpha"}, {id: 2, title: "beta"}]

and then

arr.map(item => {
  // assign item.id and element to the signal or store
  return (
    <>
      <Foo ref />
    </>
  )
})
#

does this make sense?

#

specifically it is a dialog element, and i need to call the showModal() on the ref.

#

or .close()

outer plaza
#
import { useSignal, useTask$, component$ } from '@builder.io/qwik';

const arrayData = [{id: 1, title: "alpha"}, {id: 2, title: "beta"}];

// FooRefs component
const FooRefs = component$(() => {
  const fooRefs = useSignal<Array<HTMLDialogElement>>([]);

  // Map over
  return (
    <>
      {arrayData.map((item, index) => 
        <Foo index={index} id={item.id} key={item.id} fooRefs={fooRefs} />
      )}
    </>
  );
});

// Foo component where we assign the ref
export const Foo = component$((props: { index: number, fooRefs }) => {
  const dialogRef = useSignal<HTMLDialogElement>();

  useTask$(() => {
    props.fooRefs.value[props.index] = dialogRef.value;
  });

  return (
    <dialog ref={dialogRef}>
      {/* Rest of JSX */}
    </dialog>
  );
});


// In some random parent
return <FooRefs />;
#

I think you'd want something like this

mellow turret
#

thanks, i will try it.

outer plaza
#

Then maybe something like this

#

in a visible task

#
dialogRef.value?.showModal();
#

for your dialog

#

Ah don't forget to put a track on the task

#

woops

#

Ah you might need a track might not. I actually don't think you do

#

Since it should only assign once for that component

mellow turret
#

i will have to tinker around.

#

i have also tried another solution, which uses signal to track if it is open or not, and based on that i call showModal or close within the dialog.

#

i first wanted to use useVisibleTask$, but that didn't allow me to track the prop, which was not a signal.

outer plaza
#

for example it could be array length

mellow turret
#

i used useStore6, not useSignal.

#

i misspoke.