-
-
Notifications
You must be signed in to change notification settings - Fork 96
-
-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Select model.bind with server-side options #94
Comments
Great question- here's a few options: brute forceimport {HttpClient} from 'aurelia-http-client';
import {employeeComparer} from './employees';
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);
})
]).then(() => {
var assignee = this.job.assignee;
if (assignee) {
this.job.assignee = this.employees.filter(employee => employeeComparer(employee, assignee))[0];
}
});
}
} converterexport class EmployeeToIDConverter {
toView(employee, employees) {
return employee ? employee.id : null;
}
fromView(id, employees) {
return id ? employees.filter(e => e.id === id)[0] : null;
}
} <select value.bind="job.assignee | employeeToID:employees">
<option repeat.for="employee of employees" model.bind="employee | employeeToID:$parent.employees">${employee.name}</option>
</select> enhance Aurelia's select binding logicMaybe we should add support for an <select value.bind="job.assignee" equality-comparer.bind="employeeComparer">
<option repeat.for="employee of employees" model.bind="employee">${employee.name}</option>
</select> What do you think? |
Thank you @jdanyow for your suggestions! After further investigation, I'm tempted to use the |
I came up to this var map = new Map();
var reviver = function(k, v) {
if (v === null || Array.isArray(v)) return v;
if (typeof v !== 'object') return v;
var key = JSON.stringify(v); // this is a simplified strategy to guess object identity
if (map.has(key)) {
return map.get(key);
}
map.set(key, v);
return v;
}; applied to the former use case: import {HttpClient} from 'aurelia-http-client';
export class Job {
constructor() {
this.http = new HttpClient();
this.map = new Map();
var _map = this.map;
this.reviver = function(k, v) {
if (v === null || Array.isArray(v)) return v;
if (typeof v !== 'object') return v;
var key = JSON.stringify(v);
if (_map.has(key)) {
return _map.get(key);
};
_map.set(key, v);
return v;
};
}
activate(params) {
return Promise.all([
this.http.get('/api/jobs/' + params.id).then(http => {
this.job = JSON.parse(http.response, this.reviver);
}),
this.http.get('/api/employees').then(http => {
this.employees = JSON.parse(http.response, this.reviver);
})
]);
}
} and the binding works like a charm (see this gist for a test in NodeJS). Obviously here I'm guessing object identity based on its string representation (which may vary between the two API requests), but one can use other strategies, e.g. key properties; also, JSON schema may help identifying the type of each property. |
Cool stuff! One question about the reviver- why not use Edit stopped being lazy and learned why 💤 Ignore this post... |
@jdanyow I'm for adding the third option you listed but with an easier name like matcher :) Even a simple object is having problems matching up. |
re-opening- @PWKad i like |
I'm using this as a Reviver now, with slight modifications from the previous one:
export class Reviver {
constructor() {
this.map = new Map();
}
revive(json, pk) {
var self = this;
return JSON.parse(json, function(k, v) {
if (v === null || Array.isArray(v)) return v;
if (typeof v !== 'object') return v;
var key = v[pk];
if (!self.map.has(key)) {
self.map.set(key, v);
return v;
};
return Object.assign(self.map.get(key), v);
});
}
} I'm still looking for a stronger strategy to discriminate object identity… P.S. I see Aurelia's |
@heruan The reviver in the http-client is definitely configurable, you can set a shared reviver using |
I really like the |
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:
and JavaScript:
where the API request
/api/jobs/:id
returns:and the
/api/employees
returns:In this case the
<select>
initial value would be the first optionJohn
instead of the correct optionJack
.The text was updated successfully, but these errors were encountered: