I am currently working on an Express app which uses EJS for the views. Each view (page) has a corresponding route with a router.get function which takes in request and response parameters, and renders the correct view - like so:
res.render('dashboard', { title: 'Dashboard' });
My question is: is it possible for me to call a function that exists in the route, from the EJS view? (for example within a button.click function etc)
So if I have a function in my route (dashboard.js) called deleteRowFromDatabase
var deleteRowFromDatabase = function(rowId) {
//Database logic here
};
And then in my view (dashboard.ejs) I want to call this function whenever a user clicks a button
$('#deleteButton').click(function() {
//Call route function somehow here???
})
Is there any way of doing this and if so, how?
Apologies if this question is not worded the best - I am pretty new to Node and Express.
Thanks in advance for any answers!
Related
Inside an application we allow users to create new records, related to an existing record. To achieve this, we use actions something like this:
createUser() {
var route = this;
var model = this.store.createRecord('user', {
client: route.modelFor('client'),
});
route.transitionTo('user.update', model);
},
The user.update route renders a user-form component, using the model that was passed in the transition. The same route is also used to update existing users.
The issue with this approach is as follows; when refreshing the page, the page errors because the route fails to find the respective record when querying the store (at this point, the URL is /users/null/update). Ideally I'd pass the client (or client.id) argument in the URL so that:
The page can be reloaded without issue.
The client associated with the user is set correctly.
How can I achieve this in Ember.js? I know that this can easily be done using nested routes (by nesting the user.update route inside a client route), but this doesn't make sense visually.
The relevant parts of the router are as follows:
this.route('clients');
this.route('client', {path: 'clients/:id'}, function() {
this.route('users');
});
this.route('user', {path: 'users/:id'}, function() {
this.route('update');
});
All I do in the user/update.hbs template is {{user-form user=model}}
The problem is that the model you just created has no id at that point because it is not saved, ember can´t route to a model without an id, if possible save the model before you try to transition to the route, if you don´t want to save the model because the user can cancel the action check this thread where a user had the same problem (if I understand you problem correctly), I provided a solution for that problem that I´m using in my own project
https://stackoverflow.com/a/33107273/2214998
I am new to backbone and I want to implement a very simple auth using backbone router.
I am actually using only the router from backbone in my app. When I start the app I render a login view and I also init the backbone router (Backbone.history.start();)
If login succeeded I call router.navigate('mainmenu', { trigger: true, replace: false }); to navigate to a new route where I render the main menu, but when I click on the browser's back button I navigate back to the login view.
Before navigating to the previous view (the login view) I want to ask the user if he wants to logout first, and if logout process goes well, then he is redirected to the login view.
How can I achieve that? I checked few other questions, but the answer is too complicated for my use case. I just want to prevent users to navigate back to specific views if they're logged in.
#Dethariel thanks for the answer. I successfully implemented some kind of session, using the built-in Backbone router. I started with their small example snippet from the Backbone.Router execute method backbone router execute snippet and did something similar to bellow:
var Router = Backbone.Router.extend({
// define routes and calkbacks
// ....
// define routes and calkbacks
execute: function(callback, args) {
// execute will be called before the callback for each specific route
// get the next route in here
var nextRoute = Backbone.history.fragment;
if(user.LoggedIn()){
// check if nextRoute is '#login*'. I could make other checks as well
if(nextRoute.indexOf('login')>-1)
prompt('Log out?');
// else continue routing
else if (callback) callback.apply(this, args);
}
else if (callback) callback.apply(this, args);
}
});
This is very minimal, and I don't think it's the best or secure way, but it's a good starting point for me.
You can add a backbone route which will handle the login page (if you haven't done that yet). Once this route is hit, you do (pseudo-code follows):
if (user.isLoggedIn()) {
if (showLogoutPrompt().decision === "logout") {
user.logout();
}
}
Hope this helps.
I want to insert a Meteor template (a simple login form) but I want to control what happens after the form is submitted. Ideally, I'd like to be able to pass a function afterLogin() to the template. But I'm quite unsure how to do this and if this is even possible.
I've recently seen an interesting package viewmodel and I'm not sure how related it is. But the goal in this context is basically to render a view with a different view model.
Any ideas? I'm currently using a session variable and then after login, I check that session variable to run the correct function but this is ugly and not easy to work with. Any ideas?
This is how I do it :
I assume that your login form is called from within a parent template, use the attributes syntax to pass the value of a custom helper to the data context of the login form.
<template name="parent">
{{> loginForm options=loginFormOptions}}
</template>
The helper returns an object encapsulating a function, the caller is responsible for setting this function to whatever they want.
Template.parent.helpers({
loginFormOptions:function(){
return {
afterLogin:function(){
// we assert that the context is correct :
// this will print Template.loginForm
console.log(this.view.name);
}
};
}
});
Your login form code, acting as a library, can read from its data context the function that was passed by the caller template, and then call the function with the proper this context.
Template.loginForm.events({
"submit":function(event,template){
// ...
Meteor.loginWithPassword(...,function(error){
if(error){
console.log(error);
return;
}
// guard against the existence of the custom afterLogin function
if(template.data.options && template.data.options.afterLogin){
// execute the custom function with proper context
template.data.options.afterLogin.call(template);
}
});
}
});
First of all, I would use Iron Router for navigating through different views of my application, you can get it here:
https://github.com/EventedMind/iron-router
meteor add iron:route
Then, check http://docs.meteor.com/#template_events. I would use something like:
Template.loginFormTemplate.events({
'click .loginButton': function() {
//... if success login ...
Router.go('nextScreen');
}
});
[Update 1]
I am afraid that trying to pass function to Route is an ugly approach in a sense of Meteor architecture.
You can try though, defining some Global variable, which is responsible for listening and forward-triggering events across the Routes
var eventHelper = (function () {
var self = _.extend({
afterLogin: function () {
self.trigger('forwardedEvent');
}}, Backbone.Events);
return self;
})();
Route1.events({
'click': function () {
//... Let's call after login
eventHelper.afterLogin();
}
});
eventHelper.on('forwardedEvent',function() {
// ...
});
In my application I want to read the parameters user is entering and then I want to use that parameter. http://responsive.beta.postify.com/X I want to read that X value. But first how do I ensure that the router expects a parameter?
My router is like this
Cards.Router.map(function ()
{
this.resource('cards', {path: '/'}, function ()
{
// additional child routes
this.resource('selectImage');
this.resource('message');
this.resource('recipient');
this.resource('orderStatus');
this.resource('thankyou');
this.resource('accountInfo');
this.resource('recentOrders');
this.resource('howTo');
this.resource('faq');
});
});
I want that parameter whenever the app loads. That is going to be my clientID which I would be using to fetch data from server depending upon the client.
Any thoughts on it?
When I do something like this
Cards.Router.map(function ()
{
this.resource('cards', {path: ':clientID'}, function ()
{
// additional child routes
this.resource('selectImage');
this.resource('message');
this.resource('recipient');
this.resource('orderStatus');
this.resource('thankyou');
this.resource('accountInfo');
this.resource('recentOrders');
this.resource('howTo');
this.resource('faq');
});
});
and in my browser if I put like this http://responsive.beta.postify.com/#/26 then its working but if I do like http://responsive.beta.postify.com/26 then it is not working.
To answer your question directly, to use a parameter in a route you would do something like this:
this.resource('cards', { path: '/:user_id' });
Then in your route
App.CardsRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.user_id);
}
});
This is how you can get a parameter in a certain route. Now as far as your application goes, using the code I posted above should get you that parameter as long as they access the root ('/') of your application on first load and have the user_id in the url.
I would suggest a different strategy maybe for getting the client_id and storing it for later user in your application. For example, in my application I have an Ember.Application.initializer({}) where I store the client_id. All depends on your server configuration and how your app is built, but I would definitely try and get the client_id a different way if you can!
Good luck.
I have a simple implementation of Backbone.js which goes like this -
$(document).ready(function(){
Workspace = Backbone.Router.extend({
routes: {
"/getAcademics": "academics"
},
academics: function(){
alert("ok");
$("#content").append("<div>Academics</div>");
}
});
var myWorkspace = new Workspace;
});
The link in the body is given as -
Academics
Though the router routes to the link #/getAcademics but it does not execute the function academics. Any clues as how to rectify this. Am I missing something else.
Thanks
After you instantiate your router, and before you attempt to use any of its routes, you need to call Backbone.history.start(). This will setup a listener for hash changes and call the correct route functions when needed.
You can find more information here: http://documentcloud.github.com/backbone/#History