Aurelia BindingBehavior with dynamic parameters

  • Today I recognized an, at least in my eyes, weird behavior of the BindingBehavior in Aurelia. My use case was a group of badges showing the current filter criteria sent to the backend. Instead of showing a list of unreadable codes the API expected, I wanted to lookup the name in my master data dynamically. So I created a BindingBehavior which expects as value the filtered code and as additional parameter the type of master data where to look at.


    HTML: filter-list.html
    1. <template>
    2. <div class="filter-list">
    3. <div class="filter" repeat.for="filter on filterGroups">
    4. <span class="text">${filter.value & lookup:filter.type}
    5. <span class="icon icon-close" click.delegate="removeFilter($index)"></span>
    6. </div>
    7. </div>
    8. </template>


    This seem to work or doesn't it? When the order of the filter types in the list remains the same this works quite well but when the order can change during user interaction the results become wrong. The problem here is that Aurelia reuses already rendered elements and just binds a listener to it's value to re-render the text node. This leads to the problem that the value for the lookup BindingBehavior will change but the additional parameter won't.

    In my use case this happens all the time because the user can remove and add filters of different types all the time. A working Gist.run example can be found here

    Solution

    I asked the Aurelia team about this bug on GitHub and they said this is actually kind of intended because binding behaviors should give you a ability to alter the way data in bound. At some point this makes sense to me but still I didn't expected this to happen. Now we have several possible solutions to work around this issue.


    1. The first obvious but ugly way would be to don't pass the type as an parameter but let the view engine rebind everything by working with `<template>` tags and `if` attributes.


    2. The second option was discribed from the GitHub user "bigopen" in the issue and it suggests to change the parameters to pass the filter object and the property to observe and manually listen for changes.


    This is even more no option for me than the first one^^


    3. The third way was my way to go. It actually uses internal functions but it is the most generic way. Every time the value must be rendered, the passed arguments are evaluated from the source expression. My Aurelia BindingBehavior now looks like this



    I hope this could help you a bit and if you found a better solution please let me know :)

Teilen