How to render JSP Page in Backbone - javascript

I have created a backbone project, all the html's are now converted into jsp pages.
I am able to load the page if I am using the corresponding page jsp name in the URL.
For Example
localhost:8080/abc/index.jsp || localhost:8080/abc/landing.jsp
But the problem am facing is if I have a internal page routing, for example like
Consider a login page, which has forgot password link, if i click on that it should redirect to the forgot password page which is not happening.
For navigation am using window.location.pathname = "/abc/landing.jsp"
Manually am doing like this, is there a proper way to achieve with jsp pages navigation. Please help.
Code:
forgotpassword.jsp:
<input type="hidden" value="forgotPassword">
<div id="fp"></div>
based on the input hidden parameter, am deciding which new needs to be rendered.
and the formation of url is http://localhost.abc.com:8080/test/forgotpassword.jsp
Here is my router logic:
define(['jquery', 'underscore', 'backbone'], function($, _, Backbone) {
var AppRouter = Backbone.Router.extend({
routes: {
'*': 'default'
},
});
var initialize = function() {
var apRouter = new AppRouter;
apRouter.on('route:default', function() {
if ($('input').val == "fp") {
require(['forgotpasswordView'], function(ForgotPswrd) {
var fpwrd = new ForgotPswrd();
fpwrd.render();
});
else {
require(['indexView'], function(IndexView) {
var iView = new IndexView();
iView.render();
});
}
}
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
So If i manually hit the URL appending corresponding jsp names like
http://localhost.abc.com:8080/test/forgotpassword.jsp or
http://localhost.abc.com:8080/test/index.jsp
Then pages are loading and working fine. But If am calling another view from one view to another view then it is failing.
Like landing.html:
<button id="goTo"> Go to Next View </button>
Landing View JS:
events : "click#goTo : goTo"
goTo : function(evt){
evt.preventDefault();
Backbone.history.navigate('/',true);
}
Now the forgot password page needs to load but the url is not changing just appending hash to the previous url what ever is there.
Kindly help.

Backbone relies on router to make navigation possible.So if you have a route defined in the backbone route you can navigate to it by calling the route directly using the backbone route object.In your case you can create a route for the password forgotten link and load the template or view in the function def for that route .Trigger the ROUTE 'ON CLICK'.Eg :
var AppRouter = Backbone.Router.extend({
routes: {
'*': 'default',
'/forgotpassword' : 'forgotPass'
},
});
var appRoute = new AppRouter;
forgotPass() {
// load the view here
}
$('#button').on('click',function() {
appRoute.navigate('/forgotpassword',true);
});
Please note that you cannot load a jsp page as such through backbone js as the jsp files needs to be transpiled before rendering html which cannot be done at client side. So you option is to use a templating engine like handlebar js and render the view using handlebar templates wherever necessary.

Related

Displaying ajax data in template page - Framework7

Am playing with Framework7 to do hybrid mobile app development. I have three tabs (bottom fixed), which are Home, Contacts and Settings/Profile
My app.js file looks somewhat like this:
var $$ = Dom7;
var app = new Framework7({
//.....
data: function () {
return {
user_profile : ''
}
},
on: {
tabShow( tab ) //-- when a bottom tab is clicked
{
if( $$(tab).attr('id') == 'view-settings' )
{
//.. do ajax call and get the response data in "resp"
app.data.user_profile = resp.response.profile; //setting the info to app's data
}
}
},
routes: routes
});
var settingsView = app.views.create('#view-settings', {
url: '/settings/'
});
And in routes.js:
routes = [
{
path: '/',
url: './index.html',
},
{
path: '/contacts/',
componentUrl: './pages/contacts.html',
},
{
path: '/settings/',
componentUrl: './pages/settings.html',
}
];
This Contacts page contains static content. For the Home page, am doing the AJAX API call during the deviceready state. Because am setting up some headers for authentication and stuff(for all the AJAX api calls) in there.
The problem am facing is, am unable to display the content in Settings page. It is always empty!
Am using this in that template page:
<div class="item-title item-label">Full Name - {{$root.user_profile.full_name}}</div>
I want to compile that template only when clicking the respective tab button.
Maybe that's the problem.
Any suggestions?
After going through the documentations again and again, I got another way to do this.
So, during the tabShow event, I check whether the user is accessing the Settings/Profile tab. If so, I check whether an object in app.data (eg: app.data.user_profile is empty or not(am storing the profile details there). If empty, I would do an AJAX API call to get the profile details. When the profile details is obtained, I would use app.form.fillFromData() method to fill the form. Documentation here: https://framework7.io/docs/form.html#form-data-app-methods
Make sure to name the form as well as the input elements in that form, and the same name should be use in the object(key name) when calling the fillFromData() function.
And one more thing, for the routes, /settings/ path, I used url instead of the componentUrl property to pass the url of the page.
This may not be the best solution, but am still learning. And it seems to have solved by current problem.
Thank you

Updating page through ajax and url without reloading the page (node.js)

What would be the correct way to make the inventory update without refreshing the page and accessible through both the button event and url. So that when url param id is based to the route it will update it to the specific page. Like a products page on a shopping site. Below works through the ajax request but not through the url (inventory/2) it just takes me to the posted data and not with the rendered view. I require it to be able to go to a specific page by the url so I can link to it. It also needs to be able to fall back to just standard page loading when javascript is not enabled.
View (inventory)
extends layout
block content
div.row
div.col-md-offset-2.col-md-8#inventory
a(class='btn', href='#') Get More!
script.
$(function(){
$("a.btn").on("click", function(e) {
e.preventDefault();
$.get( '/inventory/2', function(data) {
$('#inventory').html(data);
});
});
});
Routes
router.get('/inventory/:id?', function (req, res) {
if(req.params.id){
var id = req.params.id;
var data = "Updated and now on page " + id
res.send(data);
}else{
res.render('inventory');
}
});
Would recommend to have two separate sets of paths: one for the human users and one for the scripts (API). In your routes file above, you mix the two - res.send(data) is intended for the AJAX script, and res.render('inventory') for direct display in the browser in response to the user's request - that is, basically, why you don't get the result you expected.
Please see a below a simple example how the app files can be structured (extend it as you see reasonable):
View:
extends layout
block content
div.row
div.col-md-offset-2.col-md-8#inventory
= content
a(class='btn', href='#') Get More!
script.
$(function(){
$("a.btn").on("click", function(e) {
e.preventDefault();
$.get( '/api/inventory/2', function(data) {
$('#inventory').html(data);
});
});
});
Routes:
var getData = function(id) {
return "Updated and now on page " + id;
}
router.get('/api/inventory/:id', function (req, res) {
res.send(getData(req.params.id);
}
router.get('/inventory/:id?', function (req, res) {
var data;
if (req.params.id) {
data = getData(req.params.id);
} else {
data = null;
}
res.render('inventory', {content: data});
});
(note: you may have to use != content instead of = content in the Jade template if your data contains HTML.)
Now, the user can access different states of the page via urls /inventory and /inventory/2, while the AJAX call will be done using a third url, /api/inventory/2.
On top of that, you can dynamically update the url field in the user's browser as may be needed - see the answers to this question for more details.

Backbone form submit routing

Is it possible to have a Router implementation similar to the following?
var Router = Backbone.Router.extend({
routes: {
'' : 'search',
'*querystring' : 'results'
},
search: function() {
// load search view
},
results: function(querystring) {
// load search view
// make ajax request using querystring
}
});
The search view has a form that when submitted should go to the results view which will parse the url for the query, submit an ajax request and then display the response.
Obviously something like this would make more sense
'results?*querystring' : 'results'
But I can't get my form to submit the URL in that format.
When put my form action as <form action="index.html/results"> I get http://localhost:8000/index.html/results?c=foo&a=bar as my URL.
This is close, but I really need http://localhost:8000/index.html#/results?c=foo&a=bar and when I try to do this with <form action="index.html#/results"> it gives me http://localhost:8000/index.html?c=foo&a=bar#/results which is not what I want :(
This is why I would rather just have no form action and instead have a route that can will parse the query if one exists.
Ok thanks for reading. Hopefully someone understands some of that and can help me out.
don't put pushstate to true, set it to false
Backbone.js PushStates: Fallback for Internet Explorer not working
Remove form or prevent the submission
Simply get the params and trigger a route
Handle the params appropriately in the triggered route.
Router
routes:{
'search':'search' //queryString is automatically passed as last param in backbone 1.1
},
search: function(queryString){
//Write your logic to do the search
}
View:
events:{
'submit form':'preventAndNavigate'
},
preventAndNavigate: function(e){
e.preventDefault();
var query = $(e.currentTarget).serialize();
Backbone.history.navigate('search?'+query,{trigger:true});
}
Docs :
Backbone Routers now handle query params in route fragments, passing them into the handler as the last argument. Routes specified as strings should no longer include the query string ('foo?:query' should be 'foo').
References :
http://backbonejs.org/#changelog

How to get current url (including the part after hash) with Ember

I need to get current url from Ember as a "redirectTo" parameter. The parameter will be used to redirect users back to the same page after they login from other app. The url looks like
http://test.com/apps/#/tables/7
I've found this post to get currentPath/route from the application. It provides the current route name but I wonder how I can get the complete path including id from Ember. I have a nested route declaration looks like below.
App.Router.map(function() {
this.resource('tables', function() {
this.resource('table', { path: ':table_id' });
});
});
Any suggestion is welcome. Thanks!
Observe the currentPath in ApplicationController and update the current URL:
App.ApplicationController = Ember.Controller.extend({
currentPathDidChange: function() {
App.currentUrl = window.location.href;
}.observes('currentPath')
});
Can you just use window.location?
var url = window.location.href;
Thanks #Panagiotis Panagi, it works.
Furthermore, currentUrl can only be accessed from application controller, so if you want to get it from other place, you can add this code to a certain controller you want to access it :
export default Ember.Controller.extend({
needs: ['application'],
currentPath: Ember.computed.alias('controllers.application.currentPath'),
...
}

Should Backbone.js grab GET parameters from URL?

I am trying to implement a search function for my website. When the user types a search term foobar into a input box and submits it, he is redirected to http://mydomain.com/search?query=foobar.
Problem:: How should I grab the GET parameters query from the URL, and send it to the backend and get a array of results back as a JSON response? Should I even do it this way?
My current attempt below does not even cause the search function to be triggered.
Router
var AppRouter = Backbone.Router.extend({
routes: {
'search?query=:query': 'search'
// ... and some other routes
},
search: function(query) {
this.photoList = new SearchCollection();
var self = this;
this.photoList.fetch({
data: {query: query},
success: function() {
self.photoListView = new PhotoListView({ collection: self.photoList });
self.photoListView.render();
}
});
}
});
var app = new AppRouter();
Backbone.history.start({
pushState: true,
root: '/'
});
There have been several issues filed against Backbone for this very issue. There is an existing plugin that works well for this:
https://github.com/jhudson8/backbone-query-parameters
Alternatively, I'm currently using query string parameters in a mock API that matches Backbone's route matching. Looks something like this
Route
"/api/v2/application/:query"
Query
application: function(query) {
var params = $.deparam(query.slice(1));
// params.something...
}
As to your actual issue at hand how are you redirecting to index.html to support pushState?
I hit this same issue and contemplated using backbone-query-parameters, but that should be considered generally an incorrect approach.
The url query string is not meant for the front end. They get sent to the server and force a refresh when navigating from page.html to page.html?something=something.
You should be using hash fragments instead. i.e. http://www.example.com/ajax.html#key1=value1&key2=value2 then just get those values the normal backbone way and build your request params from that.
See https://github.com/jashkenas/backbone/issues/891, https://developers.google.com/webmasters/ajax-crawling/docs/specification, https://www.rfc-editor.org/rfc/rfc3986#section-3.5
You can always read the URL via jQuery URL plugin. It works well.
https://github.com/allmarkedup/jQuery-URL-Parser
There are very few cases when you need to read the URL and extract the GET params. I think that you are doing things wrong and here are my options:
1) if you are having just one page in your app (single app page) you can display results as they type in your input field or after they hit submit
2) if you are redirecting the user to a different page that means you can bootstrap data so that after the page is loaded backbone will just have to render your results and only make other requests if you change your search word
3) you can have a javascript variable which is initialized on page load directly from the server where working with GET params is probably easier

Categories