Wim Verhavert
Wim Verhavert

Reputation: 1007

Aurelia - Binding and updating a property in a custom element

I thought I would implement this quickly, but it has sent me down a rabbit hole.

I have a sidebar which is a custom element. It has 2 'modes', one for 'admin' pages and one for regular pages. There is a property in my sidebar.js that stores the mode. In the sidebar.html I use show.bind="mode!=='admin'" to show the admin part of the UI. When I change the value of the mode property in the constructor, it works as expected.

I can't seem to change the view with code.

The sidebar is part of my app.html:

<template>
<require from="./elements/sidebar"></require>
<div id="wrapper">
    <sidebar mode="regular"></sidebar>
    <main>
       <router-view></router-view>
    </main>
</div>

Now I have another view that wants to change the mode of the sidebar. In that view's js I change the value of the mode property in the activate method (I make a reference to the sidebar via injection in the constructor):

activate(params, routeConfig){
    this.sidebar.mode = "admin";
    ...
}

But nothing seems to get updated. This is my sidebar.js:

import {bindable} from "aurelia-framework";
import config from 'config';

export class Sidebar {

    @bindable mode;

    constructor(){
        ...
        this.mode = "regular"; //default value is regular
        ...
    }
}

The value of the mode is changed, but my sidebar view (the html) is not updated.

I'm still new with Aurelia and web development in general.

What is the best Aurelia way of doing this?

Upvotes: 1

Views: 1111

Answers (1)

Fabio
Fabio

Reputation: 11990

Custom-elements are transient, which means that you will get a new instance whenever you inject them. To get your Sidebar instance by DI, you have to register it first. For example:

HTML:

<template>
  <require from="./sidebar"></require>

  <sidebar view-model.ref="sidebar"></sidebar>
  <br><br>
  <router-view></router-view>
</template>

JS:

import { Sidebar } from './sidebar';
import { Container, inject } from 'aurelia-framework';

@inject(Container)
export class App {
  constructor(container) {
    this.container = container;
  }

  bind() {
    this.container.registerInstance(Sidebar, this.sidebar);
  }

}

Then, you are able to inject it into your view:

import { Sidebar } from './sidebar';
import { inject } from 'aurelia-framework';

@inject(Sidebar)
export class Route1 {

  constructor(sidebar) {
    this.sidebar = sidebar;
    this.sidebar.admin = false;
  }

}

Running example: https://gist.run/?id=0bf1e32cdccc37ceebc57c2d74ba2ca0

Upvotes: 1

Related Questions