I can specify a specific route like this in Iron Router
Router.path('/:lang/path')
and change the language according to the :lang parameter in beforeAction().
How can I do this on a global scale, e.g. every path should have a :lang prefix?
(And yes I know there is the iron-router-i18n package for this, but I cannot use it in my context).
Here's one pattern that might help you do this efficiently:
var myRoutes = ['about','info','help','item','post']; // your list of layouts (use your own names)
myRoutes.forEach(function(r){ // create all your routes as /:lang/routeName
Router.route(':lang/'+r,{ name: r, controller: 'myController' });
});
myController = RouteController.extend({ // define your own controller
onBeforeAction: function(){
Session.set('language',this.params.lang); // set the language
}
});
Related
Using Iron Router for Meteor, I know I can use the parameter 'only' or 'except' to match named routers when defining an onBeforeAction, like the example in the guide:
Router.onBeforeAction(myAdminHookFunction, {
only: ['admin']
});
Imagine I have a lot of views not needing this on before action, like public pages, and a lot needing it, like admin panel. Is there any way to apply this onBeforeAction to a group of routes without explicit list each one? I mean, for example, apply to all routes starting with '/admin', something like:
only: ['/admin/*']
Or maybe apply the onBeforeAction to a parent route and then define nested routes? (I can't find if Iron Route supports nested routes), something like:
Router.route('/admin/', {
name: 'admin',
onBeforeAction: function() {},
routes: [
{name: 'users', path: '/admin/users', action: function() {}},
{name: 'posts', path: '/admin/posts', action: function() {}}
]
})
I would suggest creating controllers. Create a "base" controller and extend it wherever needed.
I have the following routs
/product/123
/product/456
the template renders the product data and allows the user to drag things around
when I make a redirect to another product like that
Router.go("product",{_id:"456"});
the template updates the data but does not re-render the html. that means that what the user dragged stays in place. this is good for some cases but not for mine
the only solution that worked for me was to redirect to another page that sets clear template and it redirects to the product page
my router function:
Router.route('product/:_id/', {
name:"product",
data:function(){
var data = {product: Products.findOne({_id:objectId(this.params._id)})}
return data;
},
waitOn:function(){
return Meteor.subscribe('Products',this.params._id);
},
yieldTemplates: {'product': {to: 'mainArea'}},
});
I need a way to tell the router or template to reset the html
One solution is to set up an autorun in the template's onRendered function that looks for changes to the URL parameters and the resets the template as needed. Something like this:
Template.myTemplate.onRendered(function() {
var controller = Router.current()
this.autorun(function() {
var params = controller.getParams() // Reactive
// Clear up your drag interface here
});
});
By accessing controller.getParams() (the route controllers reactive parameter list) the outrun will be called when you move between routes on the same template.
I am a beginner with AngularJS and I have a little problem, I installed grunt-contrib-less to support less files instead css but now I have to declare all less styles that will be compiled into only one css file.
But my problem is normally when I'm using less, I write some code for a specific page, and here I have to write the style code for all pages. This is confusing and not really maintanable so is there a best practice to organize less styles?
I tought that there may be multiple solution:
Apply a class to body tag and change it with I don't know what
(controller, services or other)
(Import LESS file only for one page)
Generate multiple css file depending which style is compiled (but I can't do this because I can't configure grunt correctly)
Do this with DOM manipulation (but it don't find it beautifull because I think Angular must have a good way to solve that problem)
Could you explain me how to have different style for differents views ? I don't want to have the same style for all links in all views and without create hundreds classes I don't know how to do that.
Use directive
and add whatever variables/code/logic you want to add
HTML template(directive) of style can be added to your view and after compile you will get different ui for all your views
for reference read
angular directive
I solve my problem by adding specific class on body tag depending the route.
I put a variable in rootScope called 'pageStyle' with correspond to the classname that I want. This variable is updated automatically when route change (see run function). There is an event when the route change ($stateChangeSuccess or $routeChangeSuccess depending if you are using ngRoute or -angularui-routeur).
In my case i would like to add the name of the route but you can do it with the controller name or something else.
Here is an example
This is the routes :
angular
.module('frontApp', [])
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider, $mdThemingProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: '../views/home.html',
controller: function ($scope) {
$scope.msg = 'Xavier';
}
})
.state('form', {
url: '/form',
templateUrl: '../views/form.html',
controller: 'FormCtrl'
});
}])
And in the run function you will see the event bound to adapt the class when route change :
.run(function($rootScope) {
$rootScope.pageStyle = '';
// Watch state and set controller name in pageStyle variable when state change
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
event.preventDefault();
if (toState && toState.name && typeof toState.name === 'string'){
$rootScope.pageStyle = toState.name;
} else {
$rootScope.pageStyle = '';
}
});
});
Extra informations :
Note that the event called when route change is different if you are using ngroute. use "$routeChangeSuccess" if you use ngRoute and "$stateChangeSuccess" if you choose to use angular-ui-routeur
If you want to add the controller name instead the route name simply use the follow and replace 'ctrl' with you controller suffixe:
if (toState && toState.controller && typeof toState.controller !== 'function'){
$rootScope.pageStyle = toState.controller.toLowerCase().replace('ctrl','');
}
Hope it help someone else
Every example that I have seen with iron-router specifies the template name with a string. Is it possible to do this with a variable? Suppose you have several routes that all use the same dynamic path, and the same data function, but they all need different templates. Is there a way to do this without specifying a different route for every template (which would also mean changing the path I use)?
You can programmatically specify things like the template and the layout with a custom action function. The example below demonstrates showing a particular template if the required document is found based on an id in the route. You can use the same semantics for both routes and controllers.
var postsController = RouteController.extend({
waitOn: function() {
return Meteor.subscribe('post', this.params._id);
},
action: function() {
if (Posts.findOne(this.params._id)) {
this.layout('postsLayout');
this.render('posts');
} else {
this.render('notFound');
}
}
});
Once 0.8.2 is released it should be trivial to do with UI.dynamic even without Iron-Router: https://github.com/meteor/meteor/issues/2123.
I'm working on a survey/wizard type of meteor application.
The interface will only have two navigation buttons, who's caption/value will be determined dynamically based on whatever step a given user is currently at.
My question is: what markup syntax should I use within each of these two button's definitions in order to direct the Iron Router to change the route. Another words, where in the button definition should I put this: this.redirect('/anotherpath') ?
If you have a button in your template. If you are using a hrefs check answer from f3rland.
html:
<button #id="mybutton>m<Button</button>
you can catch the buttonpress event with javascript
js
Template.myTemplate.events({
'click #myButton': function(event, template) {
event.preventDefault();
Router.go('anotherpath');
}
});
The router should look like:
Router.map(function() {
this.route('anotherpath', {
path: '/',
layoutTemplate: 'myLayout',
controller: myController
});
});
I suggest you to use Iron-Router pathFor helper in your template
{{buttonText}}
That will redirect the user to the corresponding page/template.
You should also take a look at new blaze pattern to define custom block helper
Edit:
You could also use a custom helper for dynamic route as mentioned here
UI.registerHelper("_foo", function fooHelper() {
var templateName = figureOutNameDynamically(this.context.criticalInfo);
return Template[templateName];
});
<template name="foo">
{{> _foo context=.. atts=this}}
</template>
you can do this/change the route by using the action option which will automatically cal this.render().
you can do it yourself by calling the action function but I guess it is better to use onBeforeAction/after hooks