在视图中聆听财产变化

时间:2014-04-23 16:13:34

标签: javascript ember.js ember-data

我有一个使用自定义视图的模板(在Emblem中)。 模板本身是一个简单的表单,必须输入(从而设置)密码。到目前为止,我正在使用标准的Ember.TextField视图,但是,我决定向用户提供有关密码实际有多好的一些信息。

我创建的自定义视图如下所示:

div.password-strength-view
  Ember.TextField type="password" classNames="form-control" value=view.password placeholder=view.passwordPlaceholder
div.strength-bar class=view.barClass

背后的javascript:

App.PasswordStrengthView = Ember.View.extend({
  templateName: 'views/password-strength-view',

  password: '',
  passwordPlaceholder: '',

  _passwordScore: 0,
  strengthUpdater: function() {
    var calc = function(pw) {
      return ( Math.random() * 4 + 1 ); // TODO: add zxcvbn
    };

    var strength = calc(this.get('password'));
    this.set('_passwordScore', strength);

    return strength;
  }.property('password'),


  barClass: function() {
    var score = this.get('_passwordScore');
    return 'score-' + score;
  }.property('_passwordScore')
});

我现在想根据密码输入的更改(使用类.strength-bar完成)更新score-x的宽度。我还希望能够在我的模板中使用视图并设置视图的密码属性以将(1)映射到输入的值,并将(2)设置为控制器的属性。

在我的模板代码中,我尝试了这个:

App.PasswordStrengthView#edituser-pw1 password=newPassword passwordPlaceholder="Super secret"

如果我更改了Controller中的newPassword值,它将反映在视图中。视图本身不会注册任何更改。有关如何实现这一目标的任何帮助?我听错了房产吗? view.password也不起作用。

1 个答案:

答案 0 :(得分:1)

我可以在这里看到两件事:

首先,您在视图中为绑定添加了一些额外的间接,我认为这会导致问题。您创建了一个名为strengthUpdater的计算属性,其副作用是设置_passwordScore属性。由于某些运行循环魔术,barClass很可能没有看到_passwordScore已更新。

_passwordScore: 0,
strengthUpdater: function() {
  // ...
  this.set('_passwordScore', strength); // code smell

  return strength;
}.property('password'),

在计算属性函数中更改其他属性通常不是一个好主意。相反,如果您需要同时使用_passwordScorestrengthUpdater属性,请使用Ember.computed.alias

这可以简化为单个计算属性:

_passwordScore: function() {
  var calc = function(pw) {
    return ( Math.random() * 4 + 1 );
  };

  return calc(this.get('password'));
}.property('password'),

strengthUpdater: Ember.computed.alias('_passwordScore') // if you still need it

我在jsBin here中尝试过此操作,这解决了问题中最重要的部分。

其次,类名未正确应用:

div.strength-bar class=view.barClass

这变为:

<div class="strength-bar" {{bind-attr class="view.barClass"}}></div>

如您所见,您正在声明一个类属性,然后在同一属性上创建一个绑定。在我的测试中,strength-bar类被覆盖,仅应用了score-x。你会想要这个:

<div {{bind-attr class=":strength-bar view.barClass"}}></div>

抱歉,我不确定Emblem会如何实现这种语法。