Search code examples
typescriptaurelia

Aurelia child parent communication without events


I'm creating a search select component. This is the set up I have so far

Parent Element:

Typescript

export class ParentElement {
    customers: string[] = ['jon', 'mary', 'jane'];
}

HTML

<template>
    <search-select placeholder="Customer's Name" results.bind="customers"></search-select>
</template>

SearchSelectElement:

Typescript

import { bindable } from 'aurelia-framework';

export class SearchSelect {
    @bindable placeholder: string; 
    @bindable results: string[];
    query: string;
}

HTML

<template>
    <input type="search" value.bind="query" placeholder.bind="placeholder" />
    <div class="result" repeat.for="r of results">
        ${r}
    </div>
</template>

Now what I'm trying to accomplish is whenever a result is selected from the list of results to update a property on the parent element. So I tried this:

SearchSelectElement:

Typescript I added a bindable result property. And I select() method for whenever a result is selected (clicked on)

import { bindable } from 'aurelia-framework';

export class SearchSelect {
    @bindable placeholder: string; 
    @bindable results: string[];
    @bindable result: string;
    query: string;

    select(value) {
        this.result = value;
    }
}

HTML I added a click event listener for the list of results

<template>
    <input type="search" value.bind="query" placeholder.bind="placeholder" />
    <div class="result" repeat.for="r of results"  click.delegate="select(r)">
        ${r}
    </div>
</template>

ParentElement:

Typescript I added a selected property. And a selectedChanged for whenever the selected value is updated.

export class ParentElement {
    selected: string;
    customers: string[] = ['jon', 'mary', 'jane'];

    selectedChanged(value) {
        alert(value);
    }
}

HTML I added a result attribute to the child element

<search-select placeholder="Customer's Name" results.bind="customers" result.bind="selected"></search-select>

This did not work. I also tried binding a .call but haven't been able to figure that one out yet. How can I achieve what I'm trying to do. I don't want to use events because that to me just doesn't feel right or how a web component should behave


Solution

  • Bindable properties are one-way by default. You have to use two-way instead of bind or set the default binding mode as twoWay.

    You can do this:

    <search-select placeholder="Customer's Name" results.two-way="customers"></search-select>
    

    Or this:

    import { bindable, bindingMode } from 'aurelia-framework';
    
    export class SearchSelect {
        @bindable placeholder: string; 
        @bindable({ defaultBindingMode: bindingMode.twoWay }) results: string[];
        query: string;
    
        select(value) {
            this.result = value;
        }
    }
    
    <search-select placeholder="Customer's Name" results.bind="customers"></search-select>