Aurelia 访问元素';s绑定

Aurelia 访问元素';s绑定,aurelia,Aurelia,我有一个自定义属性,它处理身份验证数据,并根据说明执行一些有趣的操作 <div auth="disabled: abc; show: xyz; highlight: 123"> 在封面下,“我的身份验证”属性查看登录的用户,确定该用户是否具有正确的权限,并根据结果采取正确的操作 disabledChanged(value) { const isDisabled = this.checkPermissions(value); if (isDisabled) {

我有一个自定义属性,它处理身份验证数据,并根据说明执行一些有趣的操作

<div auth="disabled: abc; show: xyz; highlight: 123">
在封面下,“我的身份验证”属性查看登录的用户,确定该用户是否具有正确的权限,并根据结果采取正确的操作

disabledChanged(value) {
    const isDisabled = this.checkPermissions(value);
    if (isDisabled) {
        this.element.disabled = true;
    }
}
此结果需要覆盖其他绑定,这些绑定可能存在,也可能不存在。理想情况下,我希望寻找一个现有的绑定,并通过绑定行为覆盖它

constructor(element) {
    const bindings = this.getBindings(element); // What is the getBindings() function?
    const method = bindings['disabled']
    if (method) {
        bindings['disabled'] = () => this.checkPermission(this.value) && method();
    }
}
问题是这个
getBindings(元素)
函数是什么?如何访问元素上的任意绑定

编辑:此处要点:

禁用的
属性只是一个元素属性,因此您只需使用内置API即可完成此操作。请在此处查看一个可运行的示例:

使用
setAttribute
removeAttribute
(由于
disabled
属性实际上没有值,它的存在会导致元素被禁用),这就是所需的全部操作:

import {inject} from 'aurelia-framework';


@inject(Element)
export class AuthCustomAttribute {
  constructor(element) {
    this.el = element;
  }

  attached() {
    let val = false;
    setInterval(() => {
      if(this.val) {
        this.el.setAttribute('disabled', 'disabled');
      } else {
        this.el.removeAttribute('disabled');
      }
      this.val = !this.val;
    }, 1000);
  }
}

下面是新的答复

您需要直接使用绑定引擎。可运行的要点位于此处:

基本上,您需要获取原始绑定表达式,缓存它,然后用绑定表达式
true
替换它(如果
auth===false
)。然后需要解除绑定并重新绑定绑定表达式:

import {inject} from 'aurelia-framework';
import {Parser} from 'aurelia-binding';


@inject(Element, Parser)
export class AuthCustomAttribute {
  constructor(element, parser) {
    this.el = element;
    this.parser = parser;
  }

  created(owningView) {
    this.disabledBinding = owningView.bindings.find( b => b.target === this.el && b.targetProperty === 'disabled');

    if( this.disabledBinding ) {
      this.disabledBinding.originalSourceExpression =  this.disabledBinding.sourceExpression;

      // this expression will always evaluate to true
      this.expression = this.parser.parse('true');
    }
  }

  bind() {
    // for some reason if I don't do this, then valueChanged is getting called before created
    this.valueChanged();
  }

  unbind() {
    if(this.disabledBinding) {
      this.disabledBinding.sourceExpression =  this.disabledBinding.originalSourceExpression;
      this.disabledBinding.originalSourceExpression = null;

      this.rebind();

      this.disabledBinding = null;
    }
  }

  valueChanged() {
    if(this.disabledBinding ) {
      if( this.value === true ) {
        this.disabledBinding.sourceExpression =  this.disabledBinding.originalSourceExpression;
      } else {
        this.disabledBinding.sourceExpression = this.expression;
      }

      this.rebind();

    } else {
      if( this.value === true ) {
        this.el.removeAttribute('disabled');
      } else {
        this.el.setAttribute('disabled', 'disabled');
      } 
    }
  }

  rebind() {
    const source = this.disabledBinding.source;
    this.disabledBinding.unbind();
    this.disabledBinding.bind(source);
  }
}
像我在
unbind
回调中所做的那样,属性在自身之后进行清理是很重要的。老实说,我不确定在解除绑定时是否需要调用
rebind
,但这是为了完整性。

禁用的
属性只是一个元素属性,因此您可以简单地使用内置API来实现这一点。请在此处查看一个可运行的示例:

使用
setAttribute
removeAttribute
(由于
disabled
属性实际上没有值,它的存在会导致元素被禁用),这就是所需的全部操作:

import {inject} from 'aurelia-framework';


@inject(Element)
export class AuthCustomAttribute {
  constructor(element) {
    this.el = element;
  }

  attached() {
    let val = false;
    setInterval(() => {
      if(this.val) {
        this.el.setAttribute('disabled', 'disabled');
      } else {
        this.el.removeAttribute('disabled');
      }
      this.val = !this.val;
    }, 1000);
  }
}

下面是新的答复

您需要直接使用绑定引擎。可运行的要点位于此处:

基本上,您需要获取原始绑定表达式,缓存它,然后用绑定表达式
true
替换它(如果
auth===false
)。然后需要解除绑定并重新绑定绑定表达式:

import {inject} from 'aurelia-framework';
import {Parser} from 'aurelia-binding';


@inject(Element, Parser)
export class AuthCustomAttribute {
  constructor(element, parser) {
    this.el = element;
    this.parser = parser;
  }

  created(owningView) {
    this.disabledBinding = owningView.bindings.find( b => b.target === this.el && b.targetProperty === 'disabled');

    if( this.disabledBinding ) {
      this.disabledBinding.originalSourceExpression =  this.disabledBinding.sourceExpression;

      // this expression will always evaluate to true
      this.expression = this.parser.parse('true');
    }
  }

  bind() {
    // for some reason if I don't do this, then valueChanged is getting called before created
    this.valueChanged();
  }

  unbind() {
    if(this.disabledBinding) {
      this.disabledBinding.sourceExpression =  this.disabledBinding.originalSourceExpression;
      this.disabledBinding.originalSourceExpression = null;

      this.rebind();

      this.disabledBinding = null;
    }
  }

  valueChanged() {
    if(this.disabledBinding ) {
      if( this.value === true ) {
        this.disabledBinding.sourceExpression =  this.disabledBinding.originalSourceExpression;
      } else {
        this.disabledBinding.sourceExpression = this.expression;
      }

      this.rebind();

    } else {
      if( this.value === true ) {
        this.el.removeAttribute('disabled');
      } else {
        this.el.setAttribute('disabled', 'disabled');
      } 
    }
  }

  rebind() {
    const source = this.disabledBinding.source;
    this.disabledBinding.unbind();
    this.disabledBinding.bind(source);
  }
}

像我在
unbind
回调中所做的那样,属性在自身之后进行清理是很重要的。老实说,我不确定在解除绑定过程中是否需要调用
rebind
,但这是为了完整性。

这个答案的一个重要结论是要记住,当您只想在元素上设置属性值时,Aurelia不会强迫您使用一些神秘的自定义API。请注意,在我的runnable gist中,Aurelia是如何跟踪禁用属性的值变化的。感谢您的努力,但它并没有回答问题。我需要auth属性来覆盖disabled的绑定行为,该行为可能存在,也可能不存在。我已经扩展了你的要点,并将其添加到原始问题中进行演示。我想让杰里米参与进来,他会知道答案的。。可以那会更困难,但这是可能的。。让我来研究一下。我已经更新了答案和要点。它现在做你想要的。你下次进城时欠我午餐:-)一杯啤酒。看起来像2018年,所以请继续关注。这个答案的重要收获是记住,当您只想在元素上设置属性值时,Aurelia不会强迫您使用一些神秘的自定义API。请注意,在我的runnable gist中,Aurelia是如何跟踪禁用属性的值变化的。感谢您的努力,但它并没有回答问题。我需要auth属性来覆盖disabled的绑定行为,该行为可能存在,也可能不存在。我已经扩展了你的要点,并将其添加到原始问题中进行演示。我想让杰里米参与进来,他会知道答案的。。可以那会更困难,但这是可能的。。让我来研究一下。我已经更新了答案和要点。它现在做你想要的。你下次进城时欠我午餐:-)一杯啤酒。看起来像2018年,所以请继续关注。