Backbone.js: when to render views when navigating routes - view

Here are the requirements for my backbone app
display a list of folders that user has created
display the contents of a folder when a folder is clicked
Here is how I've implemented it.
AppRouter = Backbone.Router.extend({
routes: {
'': 'home',
'get/:name/:id': 'contents'
},
home: function() {
// show list of folders
},
contents: function(name, id) {
// show contents of clicked folder
}
});
This approach is giving me problems since when I click on a folder, the route gets saved in browser history and is of the structure 'domain.com#get/folder/1`. If I happen to paste this url in the address bar of browser, the list of folders won't be rendered since it doesn't match the route.
Would it be a smart strategy to display the list of folders in initialize function of router? may be create a page view which checks if the folders have already been displayed or not?

If I understand correctly, the list of folders should be shown permanently. And your application has two big views, the list of folders, and the contents. And the list of folders must be displayed all the time.
var AppRouter = Backbone.Router.extend({
// it's better to use REST names than custom ones
routes: {
'': 'index',
'get/:id/:name': 'show'
},
initialize: function(options) {
this.folders = new Folders(options.folders); // folders is your Backbone.Collection
// always show the FoldersView, something like
// new FoldersView({collection: this.folders, el: $('the folders container')})
},
index: function() {
// probably clear the contents area, something like
// $("#content").html('')
}
show: function(id, name) {
var folder = this.folders.get(id);
// create a view for this folder
// and render it in the content area, something like
// view = new FolderView(model: folder)
// $("#content").html(view.render().el)
}
})

Related

How to Dynamically bind an image from my backend server

I am currently using Vue js and trying to dynamically bind images that I'm getting from my database. I'm getting my path but the images aren't showing up. My front end is on localhost:8080 and my back end on localhost:3000.
In my app.js file, I'm establishing the the public folder as the static directory,
inside that folder I have my uploads directory which is where my images are being sent to.
app.use(express.static(path.join(__dirname, 'public')))
I'm sending my images there through multer:
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public')
},
filename: function (req, file, cb) {
cb(null, new Date().toISOString() + file.originalname)
}
})
This is an example of how I'm seeing the image's source code popping up on the inspector.
src="public/uploads/2020-03-27T12:16:43.535Zaaa.jpeg"
I want to be able to display them dynamically in my components, but the images aren't showing up.
I'm also using Vuex and storing them in an object inside my states.
I think you should access your image using the full address
src="http://localhost:3000/uploads/2020-03-27T12:16:43.535Zaaa.jpeg"

Oracle JET : Want to create a login page in which after click on login button should route me to home page

Hi I am using the example application with navigation list but I want to create a login page on top of it in which once I click login button and after authentication i have to route the application to main page.
I tried below code but nothing happened.
oj.Router.rootInstance.go('login');
please help.
Application : Oracle JET distribution
Code:
function (oj, ko, app) { // this callback gets executed when all required modules are loaded
$(function() {
function init() {
oj.Router.sync().then(
function () {
// Bind your ViewModel for the content of the whole page body.
ko.applyBindings(app, document.getElementById('globalBody'));
// navigate the user to login or wherever you want them to be now
oj.Router.rootInstance.go('login');
},
function (error) {
oj.Logger.error('Error in root start: ' + error.message);
}
);
}
You'll want to move your router go() commands out of the main.js and into a viewModel that backs the login page and only runs if and when the user passes your authentication test by entering the right username/password.
If login is the default page you want them to see, change the router.configure and navData setup in appController.js to make that the default page:
self.router.configure({
'login': {label: 'Login', isDefault: true},
...
Have a look at the FixItFast sample code for an example of a login page and the structure that supports it. FixItFast is a much more involved example than the standard Starter templates because it assumes mobile-first, but the signin.html view and signin.js viewModel might give you good ideas.
First you make your login page as default page.
Then (in your login.html) on button click you can call a function (function in login.js) where validation of your username and password takes .
self.signIn = function()
{
//your validation
if (login==success)
{
oj.Router.rootInstance.go('dashboard');
}
else
{
alert("check your details");
}
};
Make sure that you have add your dashboard page in router config
self.router.configure({
'dashboard': {label: 'Dashboard'},
'login': {label: '',isDefault: true}
});

Can I trigger an event on a specific model in a collection in backbone?

Say I have the following structure -
Model: Folder
Collection: Folders
From within my collection view, I want to trigger an event on a folder with a specific name -
So,
FolderCollectionView = Backbone.View.extend({
...
...
editFolder: function() {
this.collection.findWhere({ name: "abcd" }).trigger("editThisFolder");
}
});
FolderModelView = Backbone.View.extend({
...
...
editThisFolder: function() {
//This should get called
}
});
Is this possible? I'm using event aggregators, however, i haven't found a way wherein, I can trigger an event on a specific folder, I can make the folder view subscribe to a collection view event, but then all folder views respond to that event, I haven't found a way to make only a specific folder view respond to a collection event. Or somehow trigger an event on a specific folder view from the collection view.
I'm new to this, so let me know if i'm missing something important.
Event aggregator reference - http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/
Backbone has underscore.js as a dependency. One of the reasons for this is the fact that Backbone.js Collections implement a whole lot of underscore methods. So your solution should work
this.collection.findWhere({ name: "abcd" }).trigger("editThisFolder");
Then of course you should make your FolderView listen to that event and call the function
var FolderView = Backbone.View.extend({
initialize: function() {
// assuming a folder model assigned to each view
this.listenTo(this.model, 'editThisFolder', this.editThisFolder);
}
});
Did this answer your question?

Backbone: How to dispose a view/model when navigating to a route?

I am creating a webapp where user creates an inventory of items and he uses folders to categorize them. Now suppose I have two folders like this:
All items (route: /)
Closet items (route: #get/closet/id)
When I navigate between these routes, I want to dispose of the models rendered in the previous route. How and where should I do that? Is there an event which is triggered when I navigate to a new route where may be I can perform this operation?
There are lots of ways to approach this, and it really depends on how you're doing the navigation. If you're changing routes with actual links, or by using router.navigate(), your router will dispatch a route:<route name> event that you can listen to, passing the same arguments to the handler as it passes to the route function.
In what turned out to be a demonstration of just how long it takes to set up test case code with Backbone, I made you a jsFiddle to illustrate this approach: http://jsfiddle.net/nrabinowitz/ZrgJF/7/
A lot of this is just setup code; the important parts for this question are the router:
var MyRouter = Backbone.Router.extend({
routes: {
'view/:id' : 'openView'
},
openView: function(id) {
app.openView(id)
}
});
router = new MyRouter();
And the view, which binds removal to the route:
var MyView = Backbone.View.extend({
initialize: function(opts) {
this.id = opts.id;
router.bind('route:openView', this.dispose, this);
},
// id is the same as the route argument
dispose: function(id) {
if (id != this.id) {
this.remove();
}
}
// etc
});

Limit a firefox extension to a specific domain

I would like to write a firefox extension. This extension is not a generic extension but work specifically for a domain where I need to highlight specific html components.
How should I do that? I just want the js loaded when the user is browsing a specific domain.
My current overaly.js is basically empty (generated by the Extension Wizard):
var myextension = {
onLoad: function() {
// initialization code
this.initialized = true;
this.strings = document.getElementById("myextension-strings");
},
onMenuItemCommand: function(e) {
var promptService = Components.classes["#mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
promptService.alert(window, this.strings.getString("helloMessageTitle"),
this.strings.getString("helloMessage"));
},
onToolbarButtonCommand: function(e) {
// just reuse the function above. you can change this, obviously!
myextension.onMenuItemCommand(e);
}
};
window.addEventListener("load", myextension.onLoad, false);
And my ff-overlay.xul is:
myextension.onFirefoxLoad = function(event) {
document.getElementById("contentAreaContextMenu")
.addEventListener("popupshowing", function (e){ myextension.showFirefoxContextMenu(e); }, false);
};
myextension.showFirefoxContextMenu = function(event) {
// show or hide the menuitem based on what the context menu is on
document.getElementById("context-myextension").hidden = gContextMenu.onImage;
};
window.addEventListener("load", myextension.onFirefoxLoad, false);
I was thinking to go neanderthal and do a check inside myextension.onFirefoxLoad to see if the currentpage is the one I want but that requires the user to click the proper item on the context menu.
I'm not totally following what you have because both of those look like JS files, not XUL files. But what you probably want to do is listen for the load event coming from the web pages that are loaded. Then, in your event loader, just look at each page that loads and see whether it's coming from the specific domain you want.
A great (though not always quite as easy as it sounds) way to find out how to do something in a Firefox addon is to find another addon that does something similar. DOM Inspector and Inspect Context are your friends! The first such addon that comes to mind in this case is WikiTrust so you could try looking at that one to see if it gives you any inspiration.

Resources