pa7ryk
pa7ryk

Reputation: 551

Binding elements of array in a view

I'm new to aurelia framework. I'm trying to create a list of text inputs with inline edit. Every input should be disabled by default and after clicking on edit button it should be able to edit by removing disbaled attribute.

My welcome.js:

import {inject} from 'aurelia-framework';

@inject(HttpClient)
export class Welcome {
    heading =  'Welcome';

    inputs_list = [
        {
            'id': 1,
            'text': 'example one',
            'edit': false
        },
        {
            'id': 2,
            'text': 'example two',
            'edit': false
        },
    ];

    editInput(evt){
        let input = this.inputs_list.find( input => input.id === id );
        input.edit = true;
    }

}

My view file welcome.html:

<template>
    ${heading}
    <ul>
        <li repeat.for="input of inputs_list">
            <input ${input.edit ? '' : 'disabled'} type="text" value="${input.text}" class="inputs"/>
            <input type="button" click.delegate="editInput(input.id)" value="edit" />
        </li>
    </ul>
</template>

And I'm getting a warn:

WARN [templating-binding] Unknown binding command. Object {defaultBindingMode: null, attrName: "${input", attrValue: "", command: "edit", expression: null}

I have already found solution by modifying editInput method and passing $event as a parameter:

editInput(evt){
    let inputs = evt.target.parentNode.getElementsByClassName('inputs');
    Array.from(inputs).forEach( input => input.removeAttribute('disabled') );

}

It works but I'd like to know what is the proper way to achieve this?

Upvotes: 0

Views: 682

Answers (2)

Ashley Grant
Ashley Grant

Reputation: 10887

Aurelia is getting confused b/c there's no attribute on input elements called ${input.edit ? '' : 'disabled'}. You need to use the binding command to bind to the disabled attribute.

It might help you to read through some getting started guides on how to work with Aurelia's binding engine. For example value="${input.text}" probably is not doing what you want it to do. To have the input.text property bound to the value of that textbox, you need to use value.bind="input.text".

Also, in the click handler, you can simply pass the item from the array instead of passing its id. click.delegate="editInput(input)" and then set the input.edit property to true in the editInput function. Alternatively, you could just do this inline in your view, as I have shown below.

Finally, inputs_list doesn't follow standard JavaScript naming conventions. You may want to consider switching to inputsList or inputList as I have shown below:

Here's an example: https://gist.run?id=69bfe207db225125237878ebd7caccd8

app.html

<template>
    ${heading}
    <ul>
        <li repeat.for="input of inputList">
            <input disabled.bind="!input.edit" type="text" value.bind="input.text" class="inputs"/>
            <input type="button" click.delegate="input.edit = true" value="edit" />
        </li>
    </ul>
</template>

app.js

import {inject} from 'aurelia-framework';

export class Welcome {
    heading =  'Welcome';

    inputList = [
        {
            'id': 1,
            'text': 'example one',
            'edit': false
        },
        {
            'id': 2,
            'text': 'example two',
            'edit': false
        },
    ];

}

Upvotes: 4

James Cootware
James Cootware

Reputation: 381

You can bind a value directly to the attribute like this:

<input disabled.bind="input.edit" type="text" value="${input.text}" class="inputs"/>

This way you won't have to fiddle with DOM queries or tinker with the attributes directly

Check out this article for more information

Upvotes: 1

Related Questions