Giter Club home page Giter Club logo

binding's Introduction

Aurelia

License: MIT npm version CircleCI TypeScript Twitter

Backers on Open Collective Sponsors on Open Collective Discord Chat

Aurelia 2

This is the Aurelia 2 monorepo, containing core and plugin packages, examples, benchmarks, and documentation for the upcoming major version of everybody's favorite modern JavaScript framework, Aurelia.

Introduction

Aurelia is a modern, front-end JavaScript framework for building browser, mobile, and desktop applications. It focuses on aligning closely with web platform specifications, using convention over configuration, and having minimal framework intrusion. Basically, we want you to just write your code without the framework getting in your way. 😉

Aurelia applications are built by composing a series of simple components. By convention, components are made up of a vanilla JavaScript or Typescript class, with a corresponding HTML template.

//app.js
export class App {
  welcome = "Welcome to Aurelia";

  quests = [
    "To seek the holy grail",
    "To take the ring to Mordor",
    "To rescue princess Leia"
  ];
}
<!-- app.html -->
<form>
  <label>
    <span>What is your name?</span>
    <input value.bind="name & debounce:500">
  </label>

  <label>
    <span>What is your quest?</span>
    <select value.bind="quest">
      <option></option>
      <option repeat.for="q of quests">${q}</option>
    </select>
  </label>
</form>

<p if.bind="name">${welcome}, ${name}!</p>
<p if.bind="quest">Now set forth ${quest.toLowerCase()}!</p>

This example shows you some of the powerful features of the aurelia binding syntax. To learn further, please see our documentation.

Feeling excited? Check out how to use makes to get started in the next section.

Note: Please keep in mind that Aurelia 2 is still in beta. A number of features and use cases around the public API are still untested and there will be a few more breaking changes.

Getting Started

First, ensure that you have Node.js v8.9.0 or above installed on your system. Next, using npx, a tool distributed as part of Node.js, we'll create a new Aurelia 2 app. At a command prompt, run the following command:

npx makes aurelia

This will cause npx to download the makes scaffolding tool, along with the aurelia generator, which it will use to guide you through the setup process. Once complete, you'll have a new Aurelia 2 project ready to run. For more information on Aurelia's use of makes, see here. If you aren't interested in taking our preferred approach to generating a project, you can also see the examples folder in this repo for pure JIT setups (no conventions) with various loaders and bundlers.

Documentation

You can read the documentation on Aurelia 2 here. Our new docs are currently a work-in-progress, so the most complete documentation is available in our getting started section. If you've never used Aurelia before, you'll want to begin with our Quick Start Guide.

Contributing

If you are interested in contributing to Aurelia, please see our contributor documentation for more information. You'll learn how to build the code and run tests, how best to engage in our social channels, how to submit PRs, and even how to contribute to our documentation. We welcome you and thank you in advance for joining with us in this endeavor.

Staying Up-to-Date

To keep up to date on Aurelia, please visit and subscribe to the official blog and our email list. We also invite you to follow us on twitter. If you have questions, have a look around our Discourse forum. For chat on Aurelia 2, join our new Aurelia 2 community on Discord. If you'd like to join the growing list of Aurelia sponsors, please back us on Open Collective.

License

Aurelia is MIT licensed. You can find out more and read the license document here.

binding's People

Contributors

alexander-taran avatar alienriver49 avatar ashleygrant avatar awilczek avatar bigopon avatar bsrdjan avatar ccantill avatar cmichaelgraham avatar davismj avatar drune avatar eisenbergeffect avatar eriktim avatar fabioluz avatar fkleuver avatar gheoan avatar jdanyow avatar jods4 avatar jonathaneckman avatar martingust avatar mbroadst avatar michaelw85 avatar plwalters avatar rkivalin avatar roelplieger avatar romkevdmeulen avatar scapal avatar scriswell avatar strahilkazlachev avatar tricknotes avatar vheissu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

binding's Issues

Add support for `this` binding to reference the current view model

Currently there's no way to reference the view-model itself from the view, and can currently only reference its properties. A way to reference the VM as a whole would be great. Currently the only way to do this is to create a property on the view model to reference itself.

Eg:

export class EntityTreeView {
    constructor(modelFactory) {
        this.treeRoot = this;
    }

    doSomethingWithNode(node) {
        something(node);
    }
}
<component model.bind="{ node: nodes, root: treeRoot }"></component>

Use case:

Trying to build out a tree, so we recursively build out each node. When the node gets clicked it needs to call a function at the root level of the tree. Don't want to have to use EventAggregator to do so.

determine what (if anything) we need to do to support <datalist>

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist

<div>Choose a browser from this list:</div>
<input list="browsers" />
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Internet Explorer">
  <option value="Opera">
  <option value="Safari">
</datalist>

Question came up in the gitter around binding an input's value to an object when using <datalist>. Each option in the datalist was using model.bind.

make preventDefault configurable on event bindings

Currently, every event is default prevented by default. This breaks the desired behavior of certain events like dragstart. We'd like a way to tell the event handler to allow default behavior. The best way to handle this might be to allow default if the event returns true.

"Binding options" should support debounce or throttling an event

Enhancement - add debounce to binding options.

Say we have an input such as -

<input value.bind="searchCriteria" onChange.bind="callServer" />

Where we want an event to take place that calls the remote server, but only after a specified amount of time, in this case 1000 milliseconds -

<input value.bind="searchCriteria" change.bind="callServer -debounce=1000" />

Documentation on withOptions() binding syntax

this options as far as i understand enables us to have multi properties in attached behavior.

but currently there is no documentation on the syntax and how it works.

thanks in advanced.

writing unittest against a class containing @bindable

I'm trying to unit test a class that contains @bindable and whenever that variable is set I get the following error

Cannot read property 'getObserversLookup' of undefined

Is there some setup or initializations that needs to be performed for this to work.

basic example

import { bindable } from 'aurelia-framework';

class Example {
  @bindable example;

  constructor() {
  }

  test() {
    this.example = "something";
  }
}


describe('the Example module', () => {
  var example;

  beforeEach(() => {
    example = new Example();
  });


  it('demonstrate failure', () => {
    example.test();
  });
});

Cheers,
Ashley

ObserverLocator assumes OoPropertyObserver when getObserver is called for an undefined property

When getObserver is called for an undefined property an instance of OoPropertyObserver is returned.

When the property later becomes defined and is not a primitive property (has a getter/setter), the incorrect observer type has already been returned to the templating system so property change events cannot be observed.

I'm thinking we should return an instance of a new class: UndefinedPropertyObserver. This new class would listen for the property to become defined using Object.observe. When this happens it would do the following:

  1. call ObserverLocator.getObserver to retrieve the correct "actual" observer.
  2. delegate the subscribe, getValue and setValue methods to the "actual" observer.
  3. funnel any existing callbacks into the "actual" observer via it's subscribe method.

note: UndefinedPropertyObserver's setValue method would need to have special handling to ensure the appropriate observer is created and change events are published.

Edit
specifically talking about cases where Object.getOwnPropertyDescriptor returns undefined. (As opposed to cases where it returns {value: undefined, writable: true, enumerable: true, configurable: true})

two way binding not working on noView custom elements

I want to write a modular system so that designers can build stuff with out having to write code. To do this I created a non visual custom element that calls a service to fetch work orders. internally it has a @bindable property called workorders.

using the control in a view that also has a bindable property called workorders, the work orders are fetched but the value does not bubble up to the view.

<get-workorders workorders.two-way="workorders" auto.bind="true"></get-workorders>

what I want to be able to do is this.

<get-workorders workorders.two-way="workorders" />
<show-workorders workorders.bind="workorders" />

when I make get-workorders a visual control by adding a template and removing the noView decorator, then the two way binding works as expected.

Summary:
Two way binding should work with a custom element that is noView

binding to a property getter uses dirty-checking

In the skeleton-navigation example app some text is bound to an es5 property

<div class="form-group">
    <label>Full Name</label>
    <p class="help-block">${fullName | upper}</p>
</div>
export class Welcome{
  constructor(){
    this.heading = 'Welcome to the Aurelia Navigation App!';
    this.firstName = 'John';
    this.lastName = 'Doe';
  }

  get fullName(){
    return `${this.firstName} ${this.lastName}`;
  }
  ...
}

When I run the app (in chrome) I can see that the fullName getter is called roughly every 120ms, despite nothing changing. So it appears to be 'falling back' to dirty-checking. Is this the expected behaviour, and is there another way to write this code so that the binding uses one of the more efficient binding mechanisms?

class.bind currently overrides any existing class definitions on the element

If i have

<div class="todo-card" class.bind="todo.completed ? 'completed' : ''"></div>

I expect that the div either becomes

<div class="todo-card completed">

or

<div class="todo-card">

Currently it becomes

<div class="completed">

or

<div class="">

I'm not sure this would be the expected behavior. I would not want to do

<div class="todo-card ${todo.completed ? 'completed': ''}"> 

in a lot of cases

Observation of an Element's "xxxx" is not supported.

When I use xxxx.two-way I get the Observation of an Element's "xxxx" is not supported. error.
Is there any kind of restriction for what properties can we bind to? I tried this with a polymer custom element so if there is a white list of properties that can be two way bound I suggest looking into the properties in the prototype of the element and allow binding on those.

The value of a model property that is bound to the 'class' attribute of an 'svg' tag is instead ending up in a 'className' attribute

Given the following custom element template...

<!-- svg.class="search" -->
<template>
  <svg role="img" class="${svg.class}">
    ...
  </svg>
</template>

The rendered output is as follows...

<svg role="img" class="${svg.class} au-target" className="search">
    ....
</svg>

Notice that ${svg.class} is still present in the class attribute of the svg tag and the values that should have replaced ${svg.class} have instead been added to a separate attribute called className. The expected behaviour is that the value of svg.class should be added to the class attribute of the svg tag.

keyboard plugin

Hi there,

Rob asked me to post this issue -- it'd be nice if there was a way to natively bind key pressed events to HTML elements in the Aurelia binding framework. For example, if enter is pressed on an input text box, Aurelia delegates to a function in the ViewModel to execute some work.

He also mentioned the current workaround is to create an Attached Behavior, exposing the event that can be delegated to a function in the ViewModel. I wracked my brain for a little bit trying to figure it out, but came up blank. Would you happen to have a snippet I can work off of?

I'm guessing the implementation on the HTML side may look something like this with the attached behavior approach?

<input type="text" enter-key-pressed.bind="enterKeyPressed()" />

Thanks!

Eric

ability to add logging info when binding to non-existent properties

the idea is that sometimes we bind to a none existent property, and the logger should tell us that this property does not exist.

but one of the great things about Aurelia is that sometimes you want to bind to dynamic properties, so making this an optional flag in logging verbosity level or something would make it better.

parser.js breaks under minification

Parser.js breaks under minification. I have yet to be able to figure out exactly what goes wrong, but it's in the constructor of the Parser class.

Here is the minified code that goes wrong

function e(){this.cache={},this.lexer=new t}

The error that get's throw is

TypeError: Cannot set property 'cache' of undefined

Will do some more investigating.

Binding to Namespaced Attributes

When bind to attributes(one-way) there are a couple of options you can either bind with attr-name.bind="variable" (also tried one-way and one-time) or using interpolation attr-name="${variable}", either way though if you try to bind to a namespaced element such as xlink:href you currently get:

Uncaught NamespaceError: Failed to execute 'setAttributeNS' on 'Element': '' is an invalid namespace for attributes.

For have the following in a controller page.js:

export class page {
    constructor(){
        this.icon = 'blah';
    }
}

and the following in page.html:

<template>
  <svg class="icon ${icon}">
    <use xlink:href="${icon}"></use>
  </svg>
</template>

As I said either of the bind's above is throwing the given error. It appears that the bug is in property-observation, in that the observer is either setting to a raw attribute or a null namespaced attribute which is causing the error.

The Lexer does not handle international characters

If the viewmodel has a property called for example 'förnamn' and tries to bind to it the lexer can't handle the charachter 'ö'. This is probably true for other international charachters too like 'å' and 'ä'.

Make ref bindings work with API properties.

If an element has multiple custom attributes on it and a ref, there should be a way to get access to any of the custom attribute class instances. Allow ref.attribute-name="someIdentifier" to be used.

support for evaluating behavior scoped arguments

In app-contacts you can do

<a href="#" click.delegate="$parent.select(contact)">
</a>

where you can pass view scoped arguments like contact

If I have a custom behavior I can't do the same

<div oribella-tap="end.call: onTap(e,data,contact);"></div>

where e and dataare behavior scoped and contact view scoped. It would be nice if the CallExpression could support evaluating behavior scoped properties somehow.
Let me know if you need more info.

this.$event is not available when evaluating at the $parent scope

If you delegate an event using the $parent scope, for example <button click.delegate="$parent.click()"></button>, this.$event is undefined within the click() function. In fact, the event is not available to such a handler at all. We would expect this.$event to be defined within every click handler, regardless of the scope.

Global Functions not available to be called in template

The following will fail.

<h2>${encodeURI(heading)}</h2>

Is this by design or a bug?

Stack trace is:

Potentially unhandled rejection [1] Error: encodeURI is not a function
    at ensureFunctionFromMap (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/ast.js:58:13)
    at CallScope.evaluate (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/ast.js:652:22)
    at CallScope.connect (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/ast.js:692:29)
    at InterpolationBinding.connect (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/binding-language.js:232:35)
    at InterpolationBinding.bind (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/binding-language.js:201:22)
    at View.bind (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/view.js:69:29)
    at RouterView.swap (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/router-view.js:85:49)
    at http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/navigation-context.js:72:37
    at Array.forEach (native)
    at http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/navigation-context.js:71:28es6-module-loader.src.js:139 (anonymous function)es6-module-loader.src.js:166 fes6-module-loader.src.js:188 i

value converter naming convention incompatible with parser

If you call aurelia.withResources(DateFormatValueConverter), the ValueConverter convention kicks in and registers the converter with the name date-format.

The hyphenated name is incompatible with the parser. This kind of error will occur:

Parser Error: Unexpected token : at column 30 in [repo.updated_at | date-format:'MMMM Do YYYY, h:mm:ss a' ]

If I rename the converter to "DateformatValueConverter" and use "dateformat" instead of "date-format" in the binding expression everything works.

Not sure if the convention or the parser should change. Changing the convention to use camel-casing seems like it would be the most straight-forward code change.

select-value binding doesn't update when static options are bound

related to aurelia/templating-resources#21

In this case the options are static but each option's value/model are data bound.

view-model:

this.value = true;

view:

  <select value.bind="value">
    <option model.bind="null">null</option>
    <option model.bind="false">false</option>
    <option model.bind="true">true</option>
  </select>

The select-value binding happens before the model bindings on the options. Since these bindings don't mutate the dom, the mutation-observer used in aurelia/templating-resources#21 doesn't help.

Writing tests for the fix... will submit PR.

Problem with click.trigger

I`am trying to use click.trigger on button element which resides in div element which has click.event.stopPropagation, when I remove click.event.stopPropagation all is working well, but when it is present click.trigger do not work

Example

<template>
<div click.delegate="delegateMethod($event)">
  <h1>test .... CCC</h1>
  <input type="text" value.bind="stringValue"/>
  <button type="button" click.trigger="callMethod()">callMethod...</button>
</div>
</template>
export class Cc {
    stringValue:string='Init value...';

    delegateMethod($event) {
      $event.stopPropagation();
      alert('delegateMethod:' + this.stringValue);
    }
    callMethod() {
      alert('callMethod:' + this.stringValue);
    }
}

Using the value binding on an input can produce 'undefined' in the input

When using a text input, If you use the value binding on an object that does not have the property on it, 'undefined' gets added into the input. Should this just be an empty string or throw an error?

e.g. model:

this.myModel = {
    name: ""
}

html:

<input  value.bind="myModel.name"  />

<input value.bind="myModel.doesNotExist" />

observing computed properties via their dependencies

@Alxandr and I were brainstorming how to get around using dirty-checking when binding computed properties (properties that have a getter function).

One idea we were throwing around was to provide a way declare the computed property's dependencies. This way aurelia could observe the computed property's dependencies and recompute the property value only when the dependencies change. If this isn't something that should be put in Aurelia directly an adapter could provide this logic (#10).

Thoughts?


First attempt (no worky):

var person = { firstName: 'Don', lastName: 'Draper' };

Object.defineProperty(person, 'fullName', {
  enumerable: true,
  configurable: true,
  get: function() { return this.firstName + ' ' + this.lastName; },
  dependencies: ['firstName', 'lastName']  // wondering if getOwnPropertyDescriptor will return this...
});


var descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');
descriptor.dependencies  // undefined :(  bummer....

Second Attempt (works but not ES6 style/if-stmt in getter is bad idea)

var person = { firstName: 'Don', lastName: 'Draper' };

Object.defineProperty(person, 'fullName', {
  enumerable: true,
  configurable: true,
  get: function(returnDependencies) {
    if (returnDependencies)
      return ['firstName', 'lastName'];    
    return this.firstName + ' ' + this.lastName; 
  }
});


var descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');
descriptor.get(true);

Third Attempt (works but ugly/even worse)

var person = { firstName: 'Don', lastName: 'Draper' };
function fullName() {
  return this.firstName + ' ' + this.lastName; 
}

fullName.dependencies = ['firstName', 'lastName'];

Object.defineProperty(person, 'fullName', {
  enumerable: true,
  configurable: true,
  get: fullName
});

var descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');

descriptor.get.dependencies;
// ["firstName", "lastName"]

Last Attempt

function declarePropertyDependencies(ctor, propertyName, dependencies) {
  var descriptor = Object.getOwnPropertyDescriptor(ctor.prototype, propertyName);
  descriptor.get.dependencies = dependencies;
}

export class Person {
  constructor() {
    this.firstName = 'Don';
    this.lastName = 'Draper'; 
  }

  get fullName() {
    return this.firstName + ' ' + this.lastName;
  }
}

declarePropertyDependencies(Person, 'fullName', ['firstName', 'lastName']);

Variation of last attempt, enabling multiple props to be configured in one call

function markComputedProperties(object, props) {
  var keys = Object.keys(props);
  for (var i = 0, l = keys.length; i < l; ++i) {
    var descriptor = Object.getOwnPropertyDescriptor(object.prototype, key);
    descriptor.get.dependencies = props[key];
  }
}

export class Person {
  constructor() {
    this.firstName = 'Don';
    this.lastName = 'Draper'; 
  }

  get fullName() {
    return this.firstName + ' ' + this.lastName;
  }
}

markComputedProperties(Person, {
  fullName: ['firstName', 'lastName']
});

Unable to parse attached behavior's options

When enabling options on an attached behaviour an exception is thrown when the attribute is being parsed.

The following example is trying to expose an option called replace, for the spinner attached behavior:

static metadata(){ return Behavior.attachedBehavior('spinner').withOptions().withProperty('value', 'valueChanged').withProperty('replace'); }

When the behavior above is used in a template, like so:

spinner.bind="value.bind: spinning; replace: true"

the parsing of the attribute fails, the stack trace is the following:

Potentially unhandled rejection [2] Error: Parser Error: Unexpected token : at column 11 in [value.bind: spinning; replace: true]
at ParserImplementation.error (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:470:21)
at ParserImplementation.parsePrimary (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:365:22)
at ParserImplementation.parseAccessOrCallMember (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:306:33)
at ParserImplementation.parsePrefix (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:297:29)
at ParserImplementation.parseMultiplicative (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:270:33)
at ParserImplementation.parseAdditive (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:252:33)
at ParserImplementation.parseRelational (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:230:33)
at ParserImplementation.parseEquality (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:208:33)
at ParserImplementation.parseLogicalAnd (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:194:33)
at ParserImplementation.parseLogicalOr (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/system/parser.js:180:33)

I tried different combinations in the attribute content, but the parser apparently does not like the ':' character.

show and if do not bind correctly with table TDs

If you have a table in which some columns are shown based on some condition, both the show.bind and if.bind fail to behave properly on TD cells in particular and they also behave differently.

The following code case shows this:

http://plnkr.co/edit/NSgsbS?p=preview

Some examples where this is of value include:
Table view configurations
Toggling columns on or off based on a condition or the data type
Hiding columns based on available real estate (adaptive column models)

Observerlocator cannot observe @bindable properties unless they are 'resolved' first

It's not possible to get an observerlocator on an @bindable property:

@inject(ObserverLocator)
export class Welcome{
  heading = 'Welcome to the Aurelia Navigation App!';
  @bindable firstName = 'John';
  lastName = 'Doe';

  constructor(observerLocator)
  {     
    //var me = this['firstName']; 
    var a = observerLocator.getObserver(this, 'firstName');
    var d = a.subscribe(()=>{});
    debugger;
  }

This throws
heckProperty.getValue (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/dirty-checking.js:77:26) {innerError: RangeError: Maximum call stack size exceeded, stack: (...), message: "Error instantiating Welcome.↵---------------------…ub/aurelia/[email protected]/dirty-checking.js:77:26)"}innerError: RangeError: Maximum call stack size exceededmessage: "Error instantiating Welcome.↵------------------------------------------------↵inner error: RangeError: Maximum call stack size exceeded↵ at Welcome.execute.BindableProperty.configureDescriptor.descriptor.get as firstName↵ at DirtyCheckProperty.getValue (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/dirty-checking.js:77:26)↵ at Welcome.execute.BindableProperty.configureDescriptor.descriptor.get as firstName↵ at DirtyCheckProperty.getValue (http://localhost:9000/jspm_packages/github/aurelia/[email protected]/dirty-checking.js:77:26)↵ ...

If I 'resolve' the property before gettting the observer, by uncommenting the line

var me = this['firstName']; 

Then everything works as expected.

value.bind issue when using optgroup in a a select

I am having issues with binding a value to the select when using optgroups

<select value.bind="selectedTheme">
    <optgroup repeat.for="theme of themes" label.bind="theme.name" >
        <option repeat.for="skin of theme.skins" value.bind="skin">
          ${skin}
        </option>
    </optgroup>
  </select>

I am trying to load the array from a json from the backend.
So in the VM the themes property is null at first . then i do a http.get , and only then is the array assigned to the themes , when i do that the items appear in the select just fine , but the current selected item won't work.

It does work if i assign an array in the view model itself without loading it from the server.

tested with version 0.4.1

AccessKeyed should observe the object[key]

Currently AccessKeyed sets up an observer for the property that accesses the object instance (scope.object) and the property that accesses the key value (scope.key) but it does not observe the object's property identified by the key.

The current behavior makes sense when the object is an array instance (although it's been argued that Aurelia should use dirty-checking in cases where AccessKeyed accesses an array).

Plunker demonstrating the issue (thanks @mattduffield)

Select model.bind with server-side options

When the selected value of a <select> is bound to a property of a server-side fetched model, and the available options are fetched with another API call, Aurelia binding cannot know which is the selected option since it comes from a separate request and it's not a reference from the options array.

Is there a best practice to handle this?

Use case HTML:

<select value.bind="job.assignee">
    <option repeat.for="employee of employees" model.bind="employee">${employee.name}</option>
</select>

and JavaScript:

import {HttpClient} from 'aurelia-http-client';

export class Job {
    constructor() {
        this.http = new HttpClient();
    }
    activate(params) {
        return Promise.all([
            this.http.get('/api/jobs/' + params.id).then(http => {
                this.job = JSON.parse(http.response);
            }),
            this.http.get('/api/employees').then(http => {
                this.employees = JSON.parse(http.response);
            })
         ]);
     }
}

where the API request /api/jobs/:id returns:

{
    "id": 1234,
    "assignee": {
       "name": "Jack",
       "age": 20
    }
}

and the /api/employees returns:

[
   {
       "name": "John",
       "age": 28
    }, {
       "name": "Jack",
       "age": 20
    }
]

In this case the <select> initial value would be the first option John instead of the correct option Jack.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.