Aurelia 绑定到带有参数的函数并强制更新

Aurelia binding to a function with parameter and forcing update

我已经将一个 isSelected(item) 函数绑定到我的按钮,它将切换 class 以显示它是否被选中,但是这个函数不会在更改时更新。

我不能使用计算的 属性,因为它需要一个参数。

有什么方法可以使它与绑定函数一起工作并使用 @computedFrom 装饰器或类似的东西让它理想地更新吗?

此处示例:

https://codesandbox.io/s/aurelia-typescript-sandbox-8oksr?fontsize=14

您会注意到第 2 个人已通过该功能正确绑定,但单击其他​​项目不会更新 UI。

-

这样做的原因

我想这样做的原因是源数组有点复杂。而不是我在这里作为示例给出的人员数组。我的真实域更接近于包含项目的框列表,这些框可以包含其他框(可能无限),其中可以在任何级别选择项目。

更新 2

所以我 运行 跨越 this issue on github。其中一个答案表明,将观察到的项目自动传递到方法中会使该方法可观察。目前,您仅将 person 传递给 isSelected()。但是,人并没有被改变。我认为您可以通过像这样更改 isSelected() 方法来完成您正在寻找的内容(注意在按钮的 class 绑定中对 isSelected 的调用的更改):

vm.ts

public isSelected(person, length){
   return this.selections.find(item => item.name === person.name);
}

view.html

<button
    class="btn-gradient mini ${isSelected(person, selections.length) ? 'green': 'red'}"
    click.delegate="selectPerson(person)"
    repeat.for="person of people">
    ${person.name}
  </button>

示例:https://codesandbox.io/s/aurelia-typescript-sandbox-oelt7?fontsize=14

原版Post

我在尝试实施 isSelected() 方法来控制所选指标 class 时遇到了同样的问题。我调查了 @computedFrom.

我在这方面可能是错的,但据我所知,@computedFrom 只能与未参数化的 getter 一起使用。

@computedFrom('firstName', 'lastName')
get fullName() { return `${firstName} ${lastName}`}

所以我们想要做的事情的问题是我们需要将索引或项目传递给我们的方法——这破坏了我们使用 @computedFrom.

的能力

另一种方法,我不太喜欢...但是它确实有效,就是为每个添加一个isSelected 属性你的人反对。那么您的代码将如下所示:

vm.ts

selectPerson(person){
    person.isSelected = !person.isSelected;  //De-selects if already selected
}

view.html

<button
class="btn-gradient mini ${person.isSelected ? 'green': 'red'}"
click.delegate="selectPerson(person)"
repeat.for="person of people">${person.name}</button>

(或者,正如最近向我建议的那样,将你的 person 对象包装在包装器中 class)

public class SelectableWrapper {
   constructor(public person : Person, public isSelected : boolean){}
}

更新 1

要解决显示所选项目列表(以及 "coloring" 所选项目)的问题,您可以执行以下操作(除了我已经显示的内容):

vm.ts

//Remove selections property and add it as a getter
get selections(){
   return this.people.filter(p => p.isSelected);
}

view.html

<div repeat.for = "person of selections">
   ${person.name}
</div>

此处示例:https://codesandbox.io/s/aurelia-typescript-sandbox-u92nk?fontsize=14

multi select 利用信号器

import "./app.css";
import {BindingSignaler} from 'aurelia-templating-resources';
import { inject } from "aurelia-framework";

@inject(BindingSignaler)
export class App {
  message = "Hello World!";
  message2 = "Hello World2!";
  people = [{ name: "Person 1" }, { name: "Person 2" }, { name: "Person 3" }];
  selections = [];

  constructor(private signaler: BindingSignaler) {
    this.selections.push(this.people[1]);
  }

  selectPerson(person) {
    this.selections.push(person);
    this.signaler.signal('select-signal')
  }

  color(person) {
    return this.selections.includes(person) ? 'green' : 'red';
  }
}
<template>
  <h1>People</h1>

  <div repeat.for="person of selections">
    ${person.name}
  </div>

  <button
    class="btn-gradient mini ${color(person) & signal:'select-signal' }"
    click.delegate="selectPerson(person)"
    repeat.for="person of people"
  >
    ${person.name}
  </button>
</template>

单身select

selected 添加到 class, 在更改时分配 person 然后使用 selected === person 作为条件

import "./app.css";

export class App {
  message = "Hello World!";
  message2 = "Hello World2!";
  people = [{ name: "Person 1" }, { name: "Person 2" }, { name: "Person 3" }];
  selections = [];

  // add selected
  selected = null;

  constructor() {

    // use selectPerson
    this.selectPerson(this.people[1]);
  }

  selectPerson(person) {
    this.selections.push(person);

    // assign person to selected
    this.selected = person;
  }
}

<template>
  <h1>People</h1>

  <div repeat.for="person of selections">
    ${person.name}
  </div>

  <!-- use `selected === person` as condition -->
  <button
    class="btn-gradient mini ${selected === person ? 'green': 'red'}"
    click.delegate="selectPerson(person)"
    repeat.for="person of people"
  >
    ${person.name}
  </button>
</template>