Reputation: 2081
I'd like to get the value of data-url
in:
{#each profiles as p}
<div data-url={p.url} class="item" on:click={goToPage}>
<div class="row">
<div class="col s12 l4">
<div class="a">
<br />
</div>
</div>
<div class="col s12 l8">
<p>
<strong>{p.fn} {p.ln}</strong><br />
{p.ttl}
</p>
</div>
</div>
{p.dsc}
<hr />
</div>
{/each}
The function is:
const goToPage = (e) => {
var slug = e.target.querySelector("item").getAttribute("url");
console.log("slug is:", slug);
window.location.href = slug;
};
However it does not work and I get
Uncaught TypeError: Cannot read properties of null (reading 'getAttribute')
I have tried other things like
e.target.querySelector("item").getAttribute("data-url");
and
e.target.getAttribute("data-url");
but none of them worked.
Upvotes: 3
Views: 6564
Reputation: 946
The accepted answer (by @stephane-vanraes) suggests a better approach then the one from the question - no need to query the DOM when svelte provides you with a way to pass data.
That said, let's try to explain why the question's code didn't work.
The problem lies in the query part, it returns null
.
As the error points out, you end up with null.getAttribute()
.
So first, when querying by classname you should add a dot before the classname, i.e. .item
:
.querySelector(".item")
- with a dot
But this won't work either because of a more fundamental issue: You are looking for an item inside itself.
A.querySelector(B)
looks for "B" inside of "A".
Now, depending on the clicked element, e.target
could be the item itself or one of its children, so e.target.querySelector('.item')
is either looking for something it already has or looking for a parent within one of its children.
Switch to e.currentTarget
, as @TheBritishAreComing suggested, which always points to the element that listens to the event (the item) and skip the query.
Tip:
When you finally have the item element you can access its data attributes with:
itemElm.dataset.url
which is much nicer than:
itemElm.getAttribute('data-url')
.
Either way, the right approach is as mentioned in the accepted answer (+ removing the data-url attribute as it's not needed with this approach).
Upvotes: 0
Reputation: 16451
The simplest, most straightforward way is to simply pass the slug as an argument to the function instead:
<div data-url={p.url} class="item" on:click={() => goToPage(p.url)}>
and the function becomes:
const goToPage = (slug) => {
console.log("slug is:", slug);
window.location.href = slug;
};
Upvotes: 5
Reputation: 1727
e.target
references the thing you just clicked, you'll need to use currentTarget
instead and you don't need to do querySelector
EG:
var slug = e.currentTarget.getAttribute("data-url");
I've done a basic example
function goToPage(e){
console.debug(e.currentTarget.getAttribute('data-url'));
}
<div data-url="https://google.com" class="item" onClick="goToPage(event)">
<div class="row">
<div class="col s12 l4">
<div class="a">
<br />
</div>
</div>
<div class="col s12 l8">
<p>
<strong>{p.fn} {p.ln}</strong><br />
{p.ttl}
</p>
</div>
</div>
{p.dsc}
<hr />
</div>
<div data-url="https://google2.com" class="item" onClick="goToPage(event)">
<div class="row">
<div class="col s12 l4">
<div class="a">
<br />
</div>
</div>
<div class="col s12 l8">
<p>
<strong>{p.fn} {p.ln}</strong><br />
{p.ttl}
</p>
</div>
</div>
{p.dsc}
<hr />
</div>
Upvotes: 5