Short version of this question: I'm trying to re-render my ApplicationView when a specific event happens (a language change). The ApplicationView only contains a simple outlet, however on re-rendering this outlet remains empty. So, what is the correct approach to re-render an entire page?
Simplified application code (http://jsfiddle.net/6ZQh7/2/):
Ember.Handlebars.registerHelper('t', function() {
return App.get('language') == 'en' ? 'Hi there!' : 'Hallo!';
});
App = Ember.Application.create({
language: 'en',
ApplicationView: Em.View.extend({
templateName: 'application'
}),
TestView: Em.View.extend({
templateName: 'test'
}),
ApplicationController: Em.Controller.extend(),
Router: Em.Router.extend({
root: Em.Route.extend({
toggleLanguage: function(router) {
App.set('language', App.get('language') == 'en' ? 'nl' : 'en');
// view.parentView resolves to the ApplicationView
router.get('applicationController.view.parentView').rerender();
},
index: Em.Route.extend({
route: '/',
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('test')
}
})
})
})
});
Corresponding HTML:
<script type="text/x-handlebars" data-template-name="application">
<h1>{{t whatever}}</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="test">
<h2>My Test Page</h2>
<a href="#" {{action toggleLanguage}}>Toggle language.</a>
</script>
Doing some debugging (well, some; a few hours of it), it seems that when the re-render occurs, the ContainerView that renders the outlet doesn't have a context, which means no currentView (which is bound to this context), which means nothing is rendered in the outlet at all. Scratch that, there is a working context; if I call this.get('templateData.keywords.view.context')
in ContainerView#init using the debugger, I get the applicationcontroller. Interestingly enough though, this.get('templateData.keywords.view.context.view')
(which should return the view for the outlet) returns undefined, whereas `this.get('templateData.keywords.view.context').get('view') does return the view.
Context: I'm trying to write an internationalized Ember.js app, which contains a simple translation helper outputting strings in the currently set language (used in conjunction with Ember-I18n). Currently changing the language requires a reload of the page, as these language strings are unbound (and I would say rightfully so, as language changes are rare and creating bindings to every string on the page sounds like a bad idea). However, I'd like to just re-render instead of reload.
I am kinda giving the basic approach, Create language Objects as in...
App.Languages = {};
App.availableLanguages = Em.A([App.Languages.En, App.Languages.Pirate]);
App.Languages.En = Em.Object.extend({
languageName: "English",
appName: "My application Name"
})
App.Languages.Pirate = Em.Object.extend({
languageName: "Pirate",
appName: "!!!Zzzz"
})
App.set('language', App.Languages.En);
Handlebars Helper
Em.Handlebars.registerHelper('loc', function(key){
currentLanguage = Ember.get('language');
value = currentLanguage.get('key');
return Ember.String.htmlSafe(value);
})
Usage:
{{loc appName}}
Changing Language: A dropdown on the top of page as in
{{Ember.Select contentBinding=App.availableLanguages optionValuePath="content" optionLabelPath="content.languageName" selectionBinding="App.language"}}
Hence, when a language is changed, thanks to ember binding the value gets updated :)
I solved the exact same problem by adding an observer method to the application view, which listens to changes in the language setting, and if it detects a change, rerenders the view using the rerender() method.
I have a language controller:
FLOW.languageControl = Ember.Object.create({
dashboardLanguage:null,
content:[
Ember.Object.create({label: "English", value: "en"}),
Ember.Object.create({label: "Dutch", value: "nl"}),
Ember.Object.create({label: "Spanish", value: "sp"}),
Ember.Object.create({label: "French", value: "fr"})],
changeLanguage:function(){
locale=this.get("dashboardLanguage.value");
console.log('changing language to ',locale);
if (locale == "nl") {Ember.STRINGS=Ember.STRINGS_NL;}
else if (locale == "fr") {Ember.STRINGS=Ember.STRINGS_FR;}
else if (locale == "sp") {Ember.STRINGS=Ember.STRINGS_SP;}
else {Ember.STRINGS=Ember.STRINGS_EN;}
}.observes('dashboardLanguage')
});
with a dropdown in a handlebars file:
<label>Dashboard language: {{view Ember.Select
contentBinding="FLOW.languageControl.content"
optionLabelPath="content.label"
optionValuePath="content.value"
selectionBinding="FLOW.languageControl.dashboardLanguage" }}
</label>
And a (simplified) Navigation view, which renders the top navigation:
FLOW.NavigationView = Em.View.extend({
templateName: 'navigation',
selectedBinding: 'controller.selected',
onLanguageChange:function(){
this.rerender();
}.observes('FLOW.languageControl.dashboardLanguage'),
});
When the navigationView detects a language change (which was caused by the user selecting a language from the dropbox), the navigationView is rerendered.
You could do the same thing on the Application view, it is just that I only need the navigation view to be rerendered.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.