-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wip] Add temperature example to App framework. #276
[wip] Add temperature example to App framework. #276
Conversation
Cool! I think this example will be good for showing the basic interaction between Models and Views in a way that will be really helpful for people. |
Looking through the code I see one major thing that jumps out at me. It appears that the View is doing some of the Model's work. Could you refactor this such that the Model keeps its attribute values in sync when one of them changes? To avoid an infinite loops, you'll want to utilize the Also, instead of using the |
Change keydown event with valuechange. Move convert methods from the view to the model. Rename convert methods of the view to update. Add a few comments and rename variables just to be more clear. Fix a typo in app-temperature.mustache. Add event-valuechange in modules and tags in component.json.
Thanks Eric for the insightful advices. I hope I implemented them correctly. I didn't get For instance, if I add it to the set
I didn't understand how to use it. |
@albertosantini the _onCelsiusChange: function (e) {
this.set('kelvin', this._celsiusToKelvin(e.newVal));
this.set('fahrenheit', this._celsiusToFarenheit(e.newVal));
} However, if the var TRANSFORM = 'transform';
/* ... */
_onCelsiusChange: function (e) {
if (e.src !== TRANSFORM) {
this.set('kelvin', this._celsiusToKelvin(e.newVal), {src: TRANSFORM});
this.set('fahrenheit', this._celsiusToFarenheit(e.newVal), {src: TRANSFORM});
}
} This way the View will only have to:
|
@juandopazo Thanks for the details. I think I don't understand the last detail: I cannot figure out where I should write In the initializer of the view? |
In the Model's initializer, listen for the change event of each unit and change the others: /* ... */
initializer: function () {
this.after('celsiusChange', this._afterCelsiusChange);
this.after('fahrenheitChange', this._afterFahrenheitChange);
this.after('kelvinChange', this._afterKelvinChange);
},
_afterCelsiusChange: function (e) {
if (e.src !== TRANSFORM) {
this.set('kelvin', this._celsiusToKelvin(e.newVal), {src: TRANSFORM});
this.set('fahrenheit', this._celsiusToFarenheit(e.newVal), {src: TRANSFORM});
}
}
/* ... */ In the View's initializer, listen for the initializer: function () {
var temperature = this.get('model');
temperature.after('change', this.updateView, this);
this.clear();
} |
|
||
// Events are attached lazily. | ||
// They will be attached on the first call to getting the container node. | ||
myTemperatureView.get('container'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be in the render
method of the View?
Add change events to the model initializer. Add src property to the sets of the model to avoid recursion. Move round method to the view. Move the init of the view events to the view initializer. Add a few comments.
I think I implemented all the suggestions. :) Anything else? As usual I learnt a lot of things. Thanks Juan and Eric. |
// the `set` method. | ||
_CONVERSION: { | ||
value: 'conversion' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually use a variable to avoid typos, but it can be just a string. Using an attribute is probably overkill and maybe confusing, you could use a class property TemperatureModel.CONVERSION
if you don't want it to be a private variable.
I removed the fake attribute _CONVERSION used with the It seems to me elegant, because there is not need to add any variable. Gracias Juan. |
Don't thank me. I never get around to writing examples. It's easier to criticize. 👅 Kudos on the initiative! |
At the moment they fail, because I do not know how to simulate valuechange.
I added the tests for the example, but they fail, because I do not know how to simulate valuechange. Then I found a bug in the example: if I type, for instance, '3' in the fahrenheit input field, the conversion is displayed; then I type backspace and the fields are cleared; if I retype '3', the conversion is not done because there is not a change in the model (fahrenheit attribute contains 3). So I added What am I missing for the valuechange simulation and the reset of the model? |
// Usually the TemperatureModel and TemperatureView classes should be | ||
// implemented in separate files as modules. For the sake of the simplicity | ||
// those classes are here as local variables and not in a namespace as | ||
// Y.TemperatureModel and Y.TemperatureView. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think it's easier for people to distinguish between classes and variables, when the classes hang off the Y
object.
@ericf Done. Any hint for valuechange in the tests and the model reset? I think the problem with the reset is the default value NaN. |
// clientId is an unique ID automatically generated for | ||
// identifying model instances. Any constant value would be | ||
// fine. | ||
clientId = this.get('clientId'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked the old idea of using the string "conversion"
as the event source.
I'll have to look into that more. Let me do that today and I'll get back to you. |
The model is not reset if the attribute doesn't pass the validation process. If the default value is out of scope of the validation, it is impossible to reset the model.
Adding the focus to the node and waiting a few milliseconds, just to give time to the polling of the valuechange to catch the change, the tests are fine.
|
||
// This is a method used in the initialization of the attributes. | ||
_unitSetter: function (val) { | ||
return Y.Lang.isNumber(val) ? val : NaN; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bit confusing… I'm curious what you're trying to do here. Also, technically NaN
is a number :-/
console.log(typeof NaN); // => "number"
@albertosantini I wanted to give you an update on this… Last week I pulled this down locally, ran the example, and I wasn't happy with the UX. This is not your fault, rather I think you've highlighted a very common use case which the YUI App Framework doesn't have a great answer for. I'd like us to really nail a solid, robust solution/pattern that can applied anytime someone gets into a situation like this. I have a few varieties of changes to this example locally, none of which I think are solid enough yet. But I'll post some ideas here this week and we can continue to discuss and determine a bullet-proof solution for this type of data and user interaction. Again, I think we really need this example, I just want to make sure we're providing the best possible solution/pattern. |
I agree. Same feelings here. I think the long recycle of the pull and a few comments in the outdated diffs reflect what you described. I am open to any suggestion. :) |
I read Jeff's post about using after() event listeners for reacting to attribute value changes: http://fromanegg.com/post/37222972936/using-after-event-listeners-to-react-to-attribute Do you think is it a feasible approach (vs. event-valuechange)? Maybe it doesn't apply because the example uses Model and View approach (with Attribute built-in event architecture), but it would be interesting to release the example. :) |
Hi @albertosantini, I'm closing this due to a bit of a lack of activity, but I'd definitely love to see this continue if you decide working on it. We can definitely always have it published as a blog post instead, if you want to talk about some of the work you've done here. Let me know, and cheers! |
Hello @clarle. Without any news on event side or app framework, the state of art of the example would not be too much different from the proposed. I agree about closing it. Cheers! |
This example demonstrates how to create a simple temperature converter using Model and View components, highlighting validation and events features.