Array map and join in template

Hi,

I’m trying to create a list of IDs, joined with a comma, from my list of objects in a template, to use in a link.
E.g. url?shapes=1,2,3

I created a function getShapesLink to provide the link from the list of objects. However, it seems this isn’t being called when the list changes. I can see this list changing if I show it’s length, but when the length changes my function doesn’t get called:

template.html

${ regions_info.selected_shapes.length }
${ getShapesLink(regions_info.selected_shapes) }

class.js

getShapesLink(shapes) {
    console.log('getShapesLink', shapes.length);
    return 'url?shapes=' + shapes.map(s => s.id).join(',');
}

Any ideas what I’m doing wrong?
Some version numbers:

"aurelia-framework": "1.1.4",
"aurelia-templating": "1.4.2",
"aurelia-templating-binding": "1.3.0",

Many thanks,

Will.

1 Like

It looks like there shouldnt be anything wrong with it. Maybe try paste the error you got here?

Hi,

I don’t see an error, I just see the length changing on the page but at the same time I don’t see any console.log output from the getShapesLink.

I’ve just committed the current changes in https://github.com/ome/omero-iviewer/pull/311/commits/ceee1d4261a7ebfd2683d48fa3ca8ad5ec3eade6 (a few other changes included).

After selecting 1, 2 then 3 ‘shapes’ in the app, the length updates each time but the getShapesLink() appears only called at the start (I see getShapesLink 0 in the log) and it is not called again when the length changes. So I end up seeing this in the html:

3 url?shapes=

I also added a regular

<span repeat.for="shape of regions_info.selected_shapes">${shape.split(':')[0]},</span>

Which does update and I see 463,454,453, in the html.
Which is close to what I want but I don’t want the extra comma and all the span tags!

Thanks!

1 Like

I see the issue. I think you’ve hit a common issue in Aurelia template: method calls in template are treated as pure function calls. Which means as long as the arguments of the call don’t change, it won’t get called again.

In your case, the array mutated, but the property selected_shapes of regions_info hasn’t been changed, so there’s no update. Aurelia needs some extra hint what to observe to call the getShapesLink again.

One simple way to do it is to pass the length as 2nd parameter, so that it observe that too:

${ getShapesLink(regions_info.selected_shapes, regions_info.selected_shapes.length) }

or use a noop value converter, for observation purpose:

${getShapesLink(regions_info.selected_shapes) | noop: regions_info.selected_shapes.length}

brother, is | noop builtin?

1 Like

it’s a simple 1 liner so i didn’t mentioned it :sweat:

export class NoopValueConverter { toView(a) { return a } }

And actually it shoulda been named identity instead

Thanks - I just passed the length as a 2nd parameter to getShapesLink(). Seems the simplest fix.

1 Like