Reputation: 181
I have a template (in Emblem) that uses a custom view. The template itself is a simple form where one has to enter (and thereby set) a password. I was using standard Ember.TextField views until now, however, I decided to give the user some information on how good the password actually is.
The custom view I created looks like this:
div.password-strength-view
Ember.TextField type="password" classNames="form-control" value=view.password placeholder=view.passwordPlaceholder
div.strength-bar class=view.barClass
The javascript behind:
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')
});
I now want to update the width of the .strength-bar
according to changes of the password input (done with class score-x
). I also want to be able to use the view in my templates and set the password property of the view to map (1) to the value of the input and (2) to the property of the controller.
In my template code I tried this:
App.PasswordStrengthView#edituser-pw1 password=newPassword passwordPlaceholder="Super secret"
If I change the newPassword
value in my Controller, it is reflected in the view. The view itself does not register any changes. Any help on how to make this happen? Do I listen to the wrong property? view.password
doesn't work either.
Upvotes: 0
Views: 114
Reputation: 1056
There are two things I can see at fault here:
Firstly, you have added some extra indirection to your bindings in the view, which I believe is causing problems. You've created a computed property called strengthUpdater
that has a side effect of setting the _passwordScore
property. Most likely barClass
is not seeing that _passwordScore
has been updated due to some run loop magic.
_passwordScore: 0,
strengthUpdater: function() {
// ...
this.set('_passwordScore', strength); // code smell
return strength;
}.property('password'),
It is usually not a good idea to change other properties inside a computed property function. Instead, if you need both _passwordScore
and strengthUpdater
properties to be the same value, use Ember.computed.alias
.
This can be simplified to a single computed property:
_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
I tried this in a jsBin here and this fixed the most significant part of your issue.
Secondly, the class names are not being applied correctly:
div.strength-bar class=view.barClass
This becomes:
<div class="strength-bar" {{bind-attr class="view.barClass"}}></div>
As you can see, you are declaring a class attribute and then creating a binding on the same attribute. In my testing, the strength-bar
class is being overwritten and only score-x
is applied. You'll want this:
<div {{bind-attr class=":strength-bar view.barClass"}}></div>
Sorry, I am not sure how Emblem would achieve this syntax.
Upvotes: 1