Sto usando Aurelia e ho una matrice di elementi legati a una griglia e hanno una proprietà selezionata su di essi. Voglio associare un pulsante per essere abilitato quando uno qualsiasi degli elementi è vero. Posso fare un approccio a forza bruta in cui ho un getter che sta filtrando la lista e restituendo gli elementi selezionati, ma ciò significa che farei controlli sporchi costantemente nell'app e non voglio farlo. Sto sperando in un approccio più efficiente. Qualche idea?Osservare la proprietà su una serie di oggetti per qualsiasi modifica
risposta
Poche cose si potrebbe fare- supponendo che hanno il tuo caso d'uso a destra:
sporco controllo (è unico a non proprietà- un grosso problema)
export class Item {
selected = false;
}
export class ViewModel {
items = [new Item(), new Item(), new Item()];
get anySelected() {
var items = this.items, i = items.length;
while(i--) {
if (items[i].selected) {
return true;
}
}
return false;
}
}
osservare gli elementi
import {BindingEngine, inject} from 'aurelia-framework';
export class Item {
selected = false;
}
@inject(BindingEngine)
export class ViewModel {
items = [new Item(), new Item(), new Item()];
anySelected = false;
subscriptions = [];
constructor(locator) {
this.bindingEngine = bindingEngine;
}
updateAnySelected() {
var items = this.items, i = items.length;
while(i--) {
if (items[i].selected) {
this.anySelected = true;
return;
}
}
this.anySelected = false;
}
activate() {
var items = this.items, i = items.length, observer;
while(i--) {
observer = this.bindingEngine.propertyObserver(items[i], 'selected');
subscriptions.push(observer.subscribe(() => this.updateAnySelected());
}
this.updateAnySelected();
}
deactivate() {
let dispose;
while(subscription = subscriptions.pop()) {
subscription.dispose();
}
}
}
utilizzare una classe di raccolta
import {computedFrom} from 'aurelia-framework';
export class Item {
_selected = false;
constructor(parent) {
this.parent = parent;
}
@computedFrom('_selected')
get selected() {
return this._selected;
}
set selected(newValue) {
newValue = !!newValue;
if (newValue === _selected) {
return;
}
_selected = newValue;
this.parent.itemChanged(newValue);
}
}
export class Items {
items = [];
selectedCount = 0;
anySelected = false;
createItem() {
let item = new Item(this);
this.items.push(item);
return item;
}
itemChanged(selected) {
this.selectedCount += (selected ? 1 : -1);
this.anySelected = this.selectCount > 0;
}
}
export class ViewModel {
items = new Items();
constructor() {
let item = this.items.createItem();
item = this.items.createItem();
item = this.items.createItem();
}
}
utilizzare un array selectedItems
invece di un valore booleano selezionato prop
export class ViewModel {
items = [{}, {}, {}];
selectedItems = [];
selectItem(item) {
this.items.push(item);
}
deselectItem(item) {
this.items.splice(this.items.indexOf(item), 1);
}
}
per scopi di legame, utilizzare selectedItems.length
come "qualsiasi selezionato" proprietà
Oltre agli esempi del Jeremy, è possibile creare un custom setter, per esempio:
class Item {
// this is your ~private~ field
_isSelected = false;
// in our constructor, we pass the view model and the property name
constructor(vm, prop, name) {
this.vm = vm;
this.prop = prop;
this.name = name;
}
get isSelected() {
return this._isSelected;
}
// when you set the value, you increase the vm's property
set isSelected(value) {
if (value !== this._isSelected) {
this.vm[this.prop] += value ? 1 : -1;
this._isSelected = value;
}
}
}
export class MyViewModel
{
items = [];
itemsSelected = 0; // that's the property we'll pass to the class we've created
constructor()
{
for (let i = 0; i < 50; i++) {
// instead of adding a annonymous {} here, we add an instance of our class
this.items.push(new Item(this, 'itemsSelected', `Item ${i+1}`));
}
}
toggleIsSelected(item) {
item.isSelected = !item.isSelected;
}
}
ho creato un plunker per voi: http://plnkr.co/edit/OTb2RDLZHf5Fy1bVdCB1?p=preview
In questo modo, non eseguirai mai il ciclo per vedere se qualche elemento è cambiato.
Questo è lo stesso dell'esempio "use a collection class", sebbene manchi il decoratore '@computedFrom ('_ isSelected') sulla funzione getter isSelected che significa cheSelected sarà sporco. –
Grazie per il tuo aiuto! –
Penso che si possa anche sfruttare EventAggregator
come mostrato here. In questo modo non è necessario eseguire il controllo sporco tutto il tempo e invece gestire l'evento di selezione degli oggetti nella propria VM e pubblicare gli eventdata; l'utente dall'altra parte ascolterà lo stesso ed eseguirà la ginnastica necessaria.
Tuttavia, non l'ho mai usato, quindi non sono sicuro dei dettagli più profondi. Ma dalla documentazione sembra abbastanza facile.
Jeremy mi ha fatto pensare a questo in this bug. Quindi sembra che tu possa ottenere il binding aggiornandolo tramite un comportamento personalizzato. Spero che Jeremy possa confermare che non sto facendo nulla di troppo stupido qui.
usati in questo modo:
repeat.for="item of items | filter & array:'propertyName'"
Esso sovrascrive lo standard osservare il comportamento e osserva sulla matrice e la proprietà si definisce su ciascuna voce. Probabilmente può essere migliorato per essere più generico ...
function observeProperty(obj, property) {
this.standardObserveProperty(obj, property);
let value = obj[property];
if (Array.isArray(value)) {
this.observeArray(value);
for(let each of value){
this.standardObserveProperty(each, this.propertyName);
}
}
}
export class ArrayBindingBehavior {
bind(binding, source, property) {
binding.propertyName = property;
binding.standardObserveProperty = binding.observeProperty;
binding.observeProperty = observeProperty;
}
unbind(binding, source) {
binding.observeProperty = binding.standardObserveProperty;
binding.standardObserveProperty = null;
delete binding.propertyName;
}
}
- 1. Osservare una modifica a QUALSIASI proprietà di classe in Objective-C
- 2. Osservare ProprietàChanged su elementi di una raccolta
- 3. Dichiarare una serie di oggetti contenenti oggetti
- 4. Converti array di oggetti in serie di proprietà
- 5. Come ottenere la griglia delle proprietà per consentire la modifica degli oggetti per la selezione multipla
- 6. Come registrare l'ascolto per qualsiasi modifica di contatto su Android
- 7. underscore.js filtra una serie di oggetti, sulla base di un'altra
- 8. Differenza tra la modifica di una variabile e una proprietà
- 9. Modifica della proprietà di tutti gli oggetti in un database
- 10. Ordina serie da due proprietà degli oggetti utilizzando funzione anonima
- 11. sviluppatore di "Motore Taptic" su Apple Osservare
- 12. Monitorare una modifica della proprietà
- 13. DQL restituendo una serie di soggetti, invece di oggetti
- 14. Come si chiama quando si lancia una matrice di oggetti su una serie di stringhe?
- 15. Osservare la pigrizia in Haskell
- 16. JSON Deserializzazione con una serie di oggetti polimorfici
- 17. Modifica il tipo di dati di una colonna in serie
- 18. Come associare una proprietà bean a un'altra e osservare le modifiche in Spring Framework
- 19. Osservare un'espressione dall'interno di una direttiva
- 20. Modifica dei nomi di proprietà per la serializzazione
- 21. Aggiunta di oggetti a una proprietà NSMutableArray
- 22. join array di oggetti utilizzando una proprietà
- 23. Puoi avere una serie di diversi tipi di oggetti?
- 24. Osservare globali non globali
- 25. KVO per le proprietà di interi oggetti
- 26. Funzione dattiloscritto che prende uno o una serie di oggetti
- 27. costruzione Hash raggruppando array di oggetti basata su una proprietà degli oggetti
- 28. lodash: filtro array di oggetti con una diversa serie di oggetti
- 29. estrazione di proprietà da NSArray di oggetti
- 30. Associazione a DataGridView con una serie di proprietà
Fantastico! Alcune grandi opzioni qui. Grazie. –
È cambiato? –
Sì ... è cambiato? – Reft