Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aurelia: always call method in the view (problems after upgrade)

We've upgraded Aurelia (in particular aurelia-framework to 1.0.6, aurelia-bindong to 1.0.3) and now we're facing some binding issues.

There's a list of elements with computed classes, and we had a method int the custom element that contained the list:

getClass(t) {
    return '...' + 
           (this.selected.indexOf(t) !== -1
                ? 'disabled-option' :
                : ''
           ) + (t === this.currentTag 
                ? 'selected-option' 
                : ''
           );
}

And class.one-way="$parent.getClass(t)" for the list element, everything was OK.

After the upgrade it simply stopped to work, so whenever the selected (btw it's bindable) or currentTag properties were modified, the getClass method just wasn't called.

I partially solved this by moving this logic to the view:

class="${$parent.getClass(t) + (selected.indexOf(t) !== -1 ? 'disabled-option' : '') (t === $parent.currentTag ? 'selected-option' : '')}"

I know that looks, well... bad, but that made t === $parent.currentTag work, but the disabled-option class still isn't applied.

So, the question is:

How do I force Aurelia to call methods in attributes in the view?

P.S.

I understand that it might cause some performance issues.

Small note:

I can not simply add a selected attribute to the list element since I don't to somehow modify the data that comes to the custom element and I basically want my code to work properly without making too many changes.

UPD

I ended up with this awesome solution by Fabio Luz with this small edit:

UPD Here's a way to interpret this awesome solution by Fabio Luz.

export class SelectorObjectClass {
    constructor(el, tagger){
        Object.assign(this, el);
        this.tagger = tagger;
    }

    get cssClass(){
        //magic here
    }
}

and

this.shown = this.shown(e => new SelectorObjectClass(e, this));

But I ended up with this (defining an extra array).

like image 1000
Alexander Mikhalchenko Avatar asked Dec 28 '15 15:12

Alexander Mikhalchenko


1 Answers

You have to use a property instead of a function. Like this:

//pay attention at the "get" before function name
get getClass() {
    //do your magic here
    return 'a b c d e';
}

HTML:

<div class.bind="getClass"></div>

EDIT

I know that it might be an overkill, but it is the nicest solution I found so far:

Create a class for your objects:

export class MyClass {
   constructor(id, value) {
      this.id = id;
      this.value = value;
   }

   get getClass() {
      //do your magic here
      return 'your css classes';
   }
}

Use the above class to create the objects of the array:

let shown = [];
shown[1] = new MyClass('someId', 'someValue');
shown[2] = new MyClass('someId', 'someValue');

Now, you will be able to use getClass property:

<div repeat.for="t of shown" class.bind="t.getClass">...</div>

Hope it helps!

like image 160
Fabio Luz Avatar answered Nov 14 '22 02:11

Fabio Luz