Routing in BackboneJs, involving Jquery Mobile and Asp.Net MVC4 - asp.net-mvc-4

I'm trying to use backbonejs as my router, routing does not seems to work for subpath nor splat. I'm using MVC 4 together with Jquery mobile for this project and hopes it does not cause conflict in the routing.
The result of testing are below:
http://localhost gives me "Routed to home" in console. (correct)
http://localhost/#contacts gives me "Routed to contacts list" in console. (correct)
http://localhost/#contacts?1 stills gives me "Routed to contacts list" in console. (wrong)
http://localhost/#contacts/view/1 redirects me to http://localhost/contacts/view/1 and gives me a 404 error since I do not have such page. (wrong)
I have tried using splats, and I got the exact same problem as my 4th example. Please guide me on what I might be doing wrong.
Here's my code sample.
app.js
define([
'jquery',
'backbone',
'router',
], function ($, Backbone, Router) {
var initialize = function () {
$(document).on("mobileinit",
// Set up the "mobileinit" handler before requiring jQuery Mobile's module
function () {
$.mobile.ajaxEnabled = false
$.mobile.hashListeningEnabled = false
$.mobile.linkBindingEnabled = false
$.mobile.pushStateEnabled = false
$('div[data-role="page"]').live('pagehide', function (event, ui) {
$(event.currentTarget).remove();
})
});
require(["jquerymobile"], function () {
// Instantiates a new Backbone.js Mobile Router
this.router = new Router();
});
};
return {
initialize: initialize
};
});
router.js
define([
'jquery',
'jquerymobile',
'underscore',
'backbone',
'../../scripts/backbone/views/home/HomeView',
'../../scripts/backbone/views/footer/FooterView',
], function ($, Mobile, _, Backbone, HomeView, FooterView) {
var AppRouter = Backbone.Router.extend({
initialize: function () {
var homeView = new HomeView();
homeView.render();
var footerView = new FooterView();
footerView.render();
Backbone.history.start({ pushState: false });
},
routes: {
'contacts': 'contactList',
'contacts?:id': 'contactsDetail',
'contacts/view/:id': 'contactsDetail',
//'*actions': 'home',
'': 'home'
},
// Home method
home: function () {
console.log("Routed to home");
},
contactList: function () {
console.log("Routed to contacts list");
},
contactsDetail: function (id) {
console.log("Routed to contacts detail");
}
});
return AppRouter;
});

Related

How to access object on Vue front end from axios proxy

I have a locally hosted mongodb database with mongoose, express, axios, and a Vue front end. Right now I'm trying to access a single object from an exported array, but I'm missing the mark and getting "undefined" as the result.
vue.config.js:
module.exports = {
devServer: {
proxy: 'http://localhost:3000',
}
}
here's the front end Vue script meant to use the objects:
import axios from 'axios';
export default {
name: 'Game',
data () {
return {
pages: [],
currentPage: {},
pageTitle: "",
pageText: "",
options: [],
}
},
created () {
this.getPages();
},
methods: {
async getPages() {
try {
let res = await axios.get('/api/pages');
this.pages = res.data;
console.log(this.pages);
this.currentPage = this.pages[0];
console.log(this.currentPage);
return true;
} catch (error) {
console.log(error);
}
},
my "get" endpoint in pages.js:
router.get('/', async (req, res) => {
try {
let pages = await Page.find();
res.send({pages: pages}); //send result of search for pages as list of pages called "pages"
} catch (error) {
console.log(error);
res.sendStatus(500); //500 = server could not fulfill request
}
});
the route in server.js:
const pages = require('./routes/pages');
app.use('/api/pages', pages);
app.listen(3000, () => console.log('Server listening on port 3000!'));
module.exports = app;
and here's the console output, with the "pages" object from vue's data property and the "currentPage" that's supposed to be at pages[0] (printed to console in earlier example):
I can access the api at 'localhost:3000/api/pages' just fine, but how do I break into that array and access the first page object? I want to get an object from the list axios fetches from mongoose, then hold that object in a variable so I can access it's properties. The whole "pages > [[Target]] > pages > [ ]" is part of the problem I'm sure, but I don't know what to tell the code to open it.
Whoops! I realized my mistake. In pages.js I should have sent "res.send(pages);" After a whole couple days too XD

VueJS - function in import js file not getting triggered

We are building a web application using Vue JS and PHP, we are new to Vue JS. The server-side execution is fine, the API is able to fetch data as JSON. While trying out a static array display before making the API call, we find that the function in imported "app.js" is not getting called and the table displayed is empty. Please let us know what we might be doing wrong. Appreciate your help.
import Vue from 'vue';
export const MY_CONST = 'Vue.js';
export let memberList = new Vue({
el: '#members',
data: {
members: []
},
mounted: function () {
this.getAllMembers();
},
methods: {
getAllMembers: function () {
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
memberList.members = response.data.members;
});
*/
memberList.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}
}
});
This is the Vue component. The members object is empty.
<script>
import * as mykey from './app.js'
export default {
name: 'Home',
props: {
msg: String
},
data() {
return {
message: `Hello ${mykey.MY_CONST}!`,
members: mykey.memberList.members
}
}
};
</script>
You can also use this reference for current instance reference:
getAllMembers: function () {
var me = this;
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
// direct this not works here but we have
//saved this in another variable and scope of a var is there
me.members = response.data.members;
});
*/
// this reference works fine here.
this.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}

Sencha Touch 2, before filter on the router, to check for user's auth state

I am developing a Sencha Touch 2 app with user authentication.
I use a token for authentication.
The logic.
Check is a token exists in local storage:
var tokenStore = Ext.getStore('TokenStore'),
token = tokenStore.getAt(0).get('token');
If there is a token, check if it's valid.
I am doing a read from a model which is connected to my API which, returns success or fail - depending on the token - if it's valid or not.
TestApp.model.CheckAuthModel.load(1, {
scope: this,
success: function(record) {
// Here, I know the token is valid
},
failure: function() {
console.log('failure');
},
callback: function(record) {
console.log('callback');
console.log();
}
});
And here is the router, which handles the logic for the views:
Ext.define("TestApp.controller.Router", {
extend: "Ext.app.Controller",
config: {
refs: {
HomeView: 'HomeView',
LoginView: 'LoginView',
ProductsView: 'ProductsView',
ProductsViewTwo: 'ProductsViewTwo'
},
routes: {
'': 'home',
'home' : 'home',
'login' : 'login',
'products' : 'products',
'testingtwo' : 'testingtwo'
}
},
home: function () {
console.log('TestApp.controller.Router home function');
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getHomeView();
if (comp === undefined) comp = Ext.create('TestApp.view.HomeView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function() {
initialItem.destroy();
}
}
});
},
login: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getLoginView();
if (comp === undefined) comp = Ext.create('TestApp.view.LoginView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function() {
initialItem.destroy();
}
}
});
},
products: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getProductsView();
if (comp === undefined) comp = Ext.create('TestApp.view.ProductsView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function(){
initialItem.destroy();
}
}
});
},
testingtwo: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getProductsViewTwo();
if (comp === undefined) comp = Ext.create('TestApp.view.ProductsViewTwo');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function(){
initialItem.destroy();
}
}
});
},
launch: function() {
console.log('TestApp.controller.Router launch!');
}
});
Now, how can I link the router with the check auth model callback?
I want to know the auth state when the app reaches the router.
In other MVC frameworks, I could do a before filter, on the router, check for auth and handle the routes accordingly.
Can i do this in Sencha Touch 2?
Any ideas?
Hi I think this section in the documentation is exactly what you need:
before : Object
Provides a mapping of Controller functions to filter functions that are run before them when dispatched to from a route. These are usually used to run pre-processing functions like authentication before a certain function is executed. They are only called when dispatching from a route. Example usage:
Ext.define('MyApp.controller.Products', {
config: {
before: {
editProduct: 'authenticate'
},
routes: {
'product/edit/:id': 'editProduct'
}
},
//this is not directly because our before filter is called first
editProduct: function() {
//... performs the product editing logic
},
//this is run before editProduct
authenticate: function(action) {
MyApp.authenticate({
success: function() {
action.resume();
},
failure: function() {
Ext.Msg.alert('Not Logged In', "You can't do that, you're not logged in");
}
});
}
});
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.app.Controller-cfg-before
Of course, it's still up to you to decide whether you should check every time or should cache the auth result for sometime.
Updated to answer comment below
Honestly, i am not sure how they was going to declare that static method Authenticate in Sencha (you would be able to do it normally through Javascript i think, i.e.: prototype).
But there are other better options to solve just that Authenticate function:
Just create a singleton class that handle utility stuffs.
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.Class-cfg-singleton
If you really want to use MyApp, you can declare within the Ext.app.Application (in app.js). Then call it from the global instance MyApp.app.some_function(). I wouldn't exactly recommend this method because you change app.js, that might bring problem if you upgrade sencha touch.
You could implemented auth check in application's launch function or in your auth controller's init function and based on the response redirect the to appropriate url. Something like this:
TestApp.model.CheckAuthModel.load(1, {
scope: this,
success: function(record) {
this.redirectTo("home/");
},
failure: function() {
this.redirectTo("login/");
console.log('failure');
},
callback: function(record) {
console.log('callback');
console.log();
}
});

Multiple start pages in Durandal

I have included my main.js and shell.js below for reference. As you can see my default route in the shell.js is the viewmodels/search and it has a second route to viewmodels/application with can take an option parameter, which is the IDKey for a particular application. Most of the time this is how I want users to enter the system by starting with the search screen where they can search for a particular application or have the option to click a button to start a new application. However I would like to be able to publish url links that could skip the search page and start the application with the viewmodels/application page with the appropriate IDKey.
I just cannot seem to figure out how to implement this behaviour. Can anybody get me pointed in the right direction of how to implement this.
MAIN.JS
define('jquery', [], function () { return jQuery; });
define('knockout', [], function () { return ko; });
define(['durandal/system', 'durandal/app', 'durandal/viewLocator'], function (system, app, viewLocator) {
app.title = 'My App';
//specify which plugins to install and their configuration
app.configurePlugins({
router: true,
dialog: true,
widget: {
kinds: ['expander']
}
});
app.start().then(function () {
toastr.options.positionClass = 'toast-bottom-right';
toastr.options.backgroundpositionClass = 'toast-bottom-right';
viewLocator.useConvention();
app.setRoot('viewmodels/shell', 'entrance');
});
});
SHELL.JS
define(['plugins/router'], function (router) {
return {
router: router,
activate: function () {
return router.map([
{ route: '', moduleId: 'viewmodels/search', title: 'Permit Application Search', nav: true },
{ route: 'application(/:id)', moduleId: 'viewmodels/application', title: 'Permit Application', nav: true }
]).buildNavigationModel()
.activate();
}
};
});
Following your routes as shown in code, you should simply be able to publish a link like http://yourdomain.com#application/12

HandleInvalidRoute not working with Durandal

Here's my shell.js vm:
var vm = {
router: router,
auth: auth,
viewAttached: function () {
},
activate: function () {
router.useConvention();
router.handleInvalidRoute = function (route, params) {
debugger;
toastr.info('No Route Found: ' + route);
};
router.map([
{ url: 'error', moduleId: 'viewmodels/error', name: 'Error', visible: false }
]);
router.mapAuto();
if (auth.isAuthenticated)
//return router.activate('folder/2');
return router.activate('home');
else {
return router.activate('home');
}
}
};
return vm;
});
When I navigate to an invalid route (/folders, for example), the debugger in my handleInvalidRoute block isn't hit, and I get a scripterror from require.js:
GET http://appname.com/App/viewmodels/folders.js 404 (Not Found)
require.js:33 Uncaught Error: Script error
http://requirejs.org/docs/errors.html#scripterror require.js:8 J
require.js:8 j.onScriptError
That's all I have to work with. Any idea what's going on?
This has been answered by #EisenbergEffect in the Durandal newsgroup https://groups.google.com/forum/#!topic/durandaljs/eZrIcgn3aU8.
It is because you called mapAuto which always attempts to map urls to
modules, whether or not they actually exist. Effectively,
handleInvalidRoute will never be called.