Why first page load is slow with ASP.MVC + AngularJS - angularjs

I have an application with ASP.NET MVC and AngularJS.
My route are manage by AngularJS with ui-router.
The first time AngularJS load the partialview it's more slow then the second. What causes this ?
There are my codes:
AngularJS
app.config(function ($httpProvider, $urlRouterProvider, $locationProvider, $stateProvider) {
$urlRouterProvider.otherwise('/home');
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$locationProvider.html5Mode(true);
var homeState = {
name: 'home',
url:'/home',
controller: 'HomeCtrl',
controllerAs:'vm',
templateUrl:'/AngularJS/Home/Home' //AngularJS is a Area/Controler/Method
}
var loginState = {
name: 'login',
url: '/login',
controller: 'LoginCtrl',
controllerAs: 'vm',
templateUrl: '/AngularJS/Home/Login'
}
var registrationState = {
name: 'registration',
url: '/registration',
controller: 'RegistrationCtrl',
controllerAs: 'vm',
templateUrl: '/AngularJS/Home/Registration'
}
var dashboardState = {
name: 'dashboard',
url: '/dashboard',
controller: 'DashboardCtrl',
controllerAs: 'vm',
templateUrl: '/AngularJS/Home/Dashboard'
}
...
$stateProvider.state(homeState);
$stateProvider.state(loginState);
$stateProvider.state(registrationState);
$stateProvider.state(dashboardState);
$stateProvider.state(gameState);
$stateProvider.state(userState);
$stateProvider.state(newGameState);
$stateProvider.state(platformState);
$stateProvider.state(unavailabilityState);
$stateProvider.state(teamsState);
$stateProvider.state(newTeamState);
$stateProvider.state(editTeamState);
$stateProvider.state(detailTeamState);
$httpProvider.interceptors.push(requestInterceptor);
})
ASP.NET MVC
public PartialViewResult Home()
{
ViewBag.Title = "Home";
return PartialView();
}
public PartialViewResult Login()
{
ViewBag.Title = "Login";
return PartialView();
}
public PartialViewResult Registration()
{
ViewBag.Title = "Registration";
return PartialView();
}
public PartialViewResult Dashboard()
{
ViewBag.Title = "Dashboard";
return PartialView();
}
...
Exemple load time:
First
Second

application might be trying to load large resource that you have added to template, one way of find it is using Chrome browser (it also available in other browsers as well) follow bellow steps,
right click on the page go to Inspect element and select Network tab as bellow.
there you can see the time that took to load each resources , when its getting higher , site will take more time to load

Related

Getting nested views to work with multiple modules in AngularJS and ui-router

I'm working with a large AngularJS application, which has 1 large module, which I'm trying to break down into more easily managed modules.
We have several ui-views on the main page for menu, footer, content, sidebar etc.
At the moment each $stateProvider.state is populating each of these ui-views on every state change. I want to change it to only be more hierarchical and only have the root state change these. This I can do.
However, I'm having issues when I split the application into modules. I've created a Plunker to demonstrate.
(function() {
angular
.module("acme", ["ui.bootstrap", "ui.router", "acme.admin", "acme.stock"]);
angular
.module("acme")
.config(MainModuleConfig);
MainModuleConfig.$inject = ["$stateProvider", "$urlRouterProvider", "$locationProvider"];
function MainModuleConfig($stateProvider, $urlRouterProvider, $locationProvider) {
//$locationProvider.html5Mode(true);
var root = {
name: "root",
url: "/",
views: {
"menuView": {
templateUrl: "app/menu/menuTemplate.html",
},
"mainView": {
templateUrl: "app/mainTemplate.html",
controller: "MainController",
controllerAs: "vm",
}
}
};
$stateProvider
.state("root", root);
$urlRouterProvider
.otherwise("/");
}
})();
(function() {
angular
.module("acme.admin", ["ui.router"]);
angular
.module("acme.admin")
.config(AdminConfig);
AdminConfig.$inject = ["$stateProvider", "$locationProvider"];
function AdminConfig($stateProvider, $locationProvider) {
var admin = {
name: "admin",
url: "/Admin",
views: {
"menuView": {
templateUrl: "app/menu/menuTemplate.html",
},
"mainView": {
templateUrl: "app/admin/adminTemplate.html",
}
}
};
var countries = {
name: "admin.Countries",
url: "/Admin/Countries",
views: {
"adminView": {
templateUrl: "app/admin/adminCountriesTemplate.html",
controller: "AdminCountriesController",
controllerAs: "vm"
}
}
}
var people = {
name: "admin.People",
url: "/Admin/People",
views: {
"adminView": {
templateUrl: "app/admin/adminPeopleTemplate.html",
controller: "AdminPeopleController",
controllerAs: "vm"
}
}
}
$stateProvider
.state("admin", admin)
.state("admin.Countries", countries)
.state("admin.People", people);
}
})();
In the admin module and others, I don't want to have to set the "menuView" again, but I can't see how to reference the parent
I managed to fix the issue:
First I set up the root state in the main module:
var root = {
name: "root",
url:"/",
views: {
"menuView": {
templateUrl: "app/menu/menuTemplate.html",
},
"mainView": {
templateUrl: "app/mainTemplate.html",
controller: "MainController",
controllerAs: "vm",
}
}
};
Then in the child modules, I changed the main node to be a child of root and also suffixed the ui-view name with an #:
var admin = {
name: "root.admin",
url: "/Admin",
views: {
"mainView#": {
templateUrl: "app/admin/adminTemplate.html",
}
}
};
The plunker has been updated with the working example.

HTTP ERROR 404 after page refresh in ANgular JS1

I am using http-server package to run my angular js project. My directory structure is below:-
angulardemo/app/public/controller
angulardemo/app/public/app.js
angulardemo/app/public/index.html
angulardemo/app/public/view
ang my app.js file is
var app = angular.module('angulardemo', ['ngRoute', 'ngCookies'])
.constant('API_URL', 'http://127.0.0.1:8001')
.config(function ($routeProvider, $locationProvider, $httpProvider) {
$httpProvider.defaults.headers.common = {'Content-Type' : 'application/json'};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
/**
*
* Checks for url access
*/
resolver = function (access){
return {
load: function($q, AuthService, $location){
if(access){
return true
}else{
if(AuthService.checkLogin()){
return true;
}
else{
$location.path("/login");
}
}
}
}
}
$routeProvider
.when('/', {
templateUrl : "/view/home.html",
controller : 'PagesController'
})
.when('/home', {
templateUrl : "/view/home.html",
controller : 'PagesController'
})
.when('/about', {
templateUrl : "/view/about.html",
controller : 'PagesController'
})
.when('/team', {
templateUrl : "/view/team.html",
controller : 'PagesController'
})
.when('/work', {
templateUrl : "/view/work.html",
controller : 'PagesController'
})
.when('/price', {
templateUrl : "/view/price.html",
controller : 'PagesController'
})
.when('/users/:user_type', {
templateUrl : "/view/developers.html",
controller : 'UsersController'
})
.when('/user/show/:id', {
templateUrl : "/view/user.details.html",
controller : 'UsersController'
})
.when('/contact', {
templateUrl : "/view/contact.html",
controller : 'PagesController'
})
.when('/register', {
controller: 'AuthController',
templateUrl: '/view/auth/register.html',
resolve:{
loggedIn: function(AuthService, $location){
if(!AuthService.checkLogin())
return true;
else
$location.path("/home");
}
}
})
.when('/login', {
controller: 'AuthController',
templateUrl: '/view/auth/login.html',
resolve:{
loggedIn: function(AuthService, $location){
if(!AuthService.checkLogin())
return true;
else
$location.path("/home");
}
}
})
.when('/dashboard', {
controller: 'DashboardController',
templateUrl: '/view/dashboard/index.html',
pageTitle: 'dashboard',
resolve:resolver(false)
})
.when('/users_personal/:id', {
controller: 'UsersController',
templateUrl: '/view/users/personal.html',
pageTitle: 'personal_details',
resolve:resolver(false)
})
.when('/users_edu/:id', {
controller: 'UsersController',
templateUrl: '/view/users/edu.html',
pageTitle: 'edu_details',
resolve:resolver(false)
})
.when('/users_contact/:id', {
controller: 'UsersController',
templateUrl: '/view/users/contact.html',
pageTitle: 'contact_details',
resolve:resolver(false)
})
.when('/users_other/:id', {
controller: 'UsersController',
templateUrl: '/view/users/other.html',
pageTitle: 'other',
resolve:resolver(false)
})
.when('/logout', {
resolve : {
logout: function ($routeParams, $location, $http, API_URL){
$http.get(API_URL + "/api/auth/logout").success(function (response) {
if(response === "OK"){
localStorage.removeItem('auth');
$location.path('/login').replace();
}
})
}
}
})
.otherwise({
redirectTo: '/',
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
}).hashPrefix('*');
}).run(['$http', '$cookies', function($http, $cookies) {
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
}]);
when I am running project using "http-server" with in the app directory command I got url as http://127.0.0.1:8080
http://192.168.10.137:8080
all the pages are working fine but when I am refreshing the page I am getting This 127.0.0.1 page can’t be found
No web page was found for the web address: http://127.0.0.1:8080/team
HTTP ERROR 404
So can anyone please tell that what wrong thing is here. and provide the solution.
See the directory structure in git hub:-
https://github.com/sanjaysamant/angulardemo/tree/local/app
Angular js files are in the public directory
Thanks
Please see terminal screen shot:
Whenever you are on a sub-URL such as /team and you refresh the page, the Node-Server looks for a HTML-File that is in the folder team on your server, which is not what you want. You need the server to redirect all those URL's to your index.html so that it loads the Angular Application, which can then properly initialize the correct page.
You can try the following in your server.js file:
//routes
app.use('/api/auth', require('./controllers/auth/auth.controller'));
app.use('/api/users', require('./controllers/users/users.controller'));
app.use('/api/user/', require('./controllers/users/users.controller'));
// Redirect unmatched routes (All specific routes such as /api/* need to be before this call)
app.use(redirectUnmatched);
function redirectUnmatched(req, res) {
res.redirect("/");
}
What #Chnoch suggested is correct, however I want to give you a different approach.
app.get('*', function(req, res)
{
res.send('/path/to/index.html');
});
Because all requests for a page will be a GET requests, you don't need to specify POST, and with this approach it will preserve the current URL you are on (eg. if you were on http://127.0.0.1:8080/team you will refresh and still be on /team), wheras #Chnoch's approach will always redirect you back to http://127.0.0.1:8080/.
What this will do is for any request that can't be resolved by the Node server, it will just render plain index page that can then be handled by Angular's ngRoute to display templates (you can also use templating engines like EJS or Pug with this, just replace the res.send with the rendering function).
Just make sure that the above code is after ALL other routes you want to be resolved by the Node server (eg. your API etc.) so it doesn't interfere with routes after it, since this is a catch all route.

trying to go from one form to another in angularjs

I am making a project on my own to practice what I've learned about MEAN stack. In the project I want the user to fill in a form and after it is saved in the database the system to take a use to a second form to fill it in etc. I am angularjs for the front end, and within it I am using ui.route. For some reason my program doesn't go to the second program. I already read about other people with the same problem and I can't find what is wrong with my algorithm. Every form works well by itself or when I Make a call from the toolbar.
Frontend.js
angular
.module('authApp',['auth0', 'angular-storage', 'angular-jwt', 'ngMaterial', 'ui.router',
'AdminUser', 'appProfile', 'appToolbar', 'Mod-Company', 'ModShow'])
.config(function($provide, authProvider, $urlRouterProvider, $stateProvider, $httpProvider, jwtInterceptorProvider,$mdThemingProvider){
/* $mdThemingProvider.theme('docs-dark'); */
$mdThemingProvider.theme('default')
.dark();
$mdThemingProvider.alwaysWatchTheme(true);
authProvider.init({
domain: 'workflowjobs.auth0.com',
clientID: 'SjzgRRh3w4ZEFRGLdglpJYvCPCkM189w'
});
jwtInterceptorProvider.tokenGetter = function(store) {
return store.get('id_token');
}
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'components/home/home.html'
})
.state('company', {
url: '/company',
templateUrl: 'components/company/company.html'
})
.state('singlecompany', {
url: '/singlecompany',
templateUrl: 'components/singlecompany/singlecompany.html'
})
.state('show', {
url: '/show',
templateUrl: 'components/show/show-form.html'
})
.state('ticket', {
url: '/ticket',
templateUrl: 'components/ticket/ticket.html'
})
.state('useradmin', {
url: '/useradmin',
templateUrl: 'components/useradmin/useradmin.html'
})
.state('user', {
url: '/user',
templateUrl: 'components/user/user.html'
})
.state('profile', {
url: '/profile',
templateUrl: 'components/profile/profile.html',
controller: 'profileController',
controllerAs: 'user'
});
From the form I use the controller I need, display the form to be filled in by the user and then I call addcompany() after the user click on the button to save the document on the mongodb database.
<section class="table" ng-controller="CompanyCtrl">
<form name="CompanyForm">
...
<input class="form-control" ng-model="company.name" size="40">
...
<p><md-button class="md-raised md-primary md-hue-1" ng-click="addcompany()" aria-label="next">
Now in this code is where I have the problem. the $location.path('/adminuser') doesn't work:
var app = angular.module('Mod-Company', []);
app.controller('CompanyCtrl', ['$scope', '$http',
function($scope,$http){
var refresh = function() {
$http.get('http://localhost:3001/api/company').success(function(response){
$scope.companylist = response;
$scope.company = "";
});
};
refresh();
$scope.addcompany = function(){
$http.post('http://localhost:3001/api/company', $scope.company).success(function(response) {
refresh();
$location.path('/useradmin');
});
$location.path('/useradmin');
};
Instead of using $location.path('/useradmin'); try $state.go('useradmin');.
If it is still not working, it will be easier to help you if you could share your code in a https://jsbin.com or https://plnkr.co

Separate nav from ng-view

I'm brand new to Angularjs and am trying to set up a new site but I'm confused as to the set up. I have a module and am using $route to successfully navigate but I'm lost as to what to do with my nav. When I load the module I want to read my database for a list of links that the user is allowed to access then spit them out in the nav. I don't want to repeat this in every view because I don't need to. So I'm trying to figure out how to run the ajax call once and then keep changing the view (I'd also like to add a class .selected to whatever view they're on). How would I go about doing that, with a directive?
(function () {
var app = angular.module('manage', ['ngRoute', 'manageControllers']);
/*
I've tried this but obviously $http isn't injected. Can I even do that?
var thisApp = this;
$http.get('/test/angular/php/angular.php', {params: {'function': 'nav'}}).then(function successCallback(response) {
});
*/
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
}).
when('/inventory/', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
when('/inventory/:mvKey', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
when('/inventory/:mvKey/:tab', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
/* etc...*/
}
]);
})();
EDIT:
My attempt at getting the nav to run once
controllers.js
var manageControllers = angular.module('manageControllers', []);
var thisApp = this;
nav = null;
navSelected = '/';
manageControllers.controller('NavCtrl', ['$scope', '$http', function($scope, $http) {
if (thisApp.nav === null) {
$http.get('php/angular.php', {params: {'function': 'nav'}}).then(function successCallback(response) {
console.log(response.data);
thisApp.nav = response.data;
$scope.nav = thisApp.nav;
$scope.select = thisApp.navSelected;
});
} else {
$scope.nav = thisApp.nav;
$scope.select = thisApp.navSelected;
}
}]);
manageControllers.controller('DashCtrl', ['$scope', function($scope) {
thisApp.navSelected = '/';
}]);
I would swith to UI Router (https://github.com/angular-ui/ui-router) instead of $route. It allows you being much more flexible with your routing.
A Small example:
app.config(['$stateProvider',
function($stateProvider) {
$stateProvider.
state('/', {
url: '/',
views: {
'': {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
},
'nav#': {
templateUrl: 'path/to/nav.html',
controller: 'NavCtrl'
},
}
}).
state('/inventory/', {
url: '/',
views: {
'': {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
},
'nav#': {
templateUrl: 'path/to/nav.html',
controller: 'NavCtrl'
},
}
}).
// ...
and in your index.html
<div ui-view="nav"></div>
<div ui-view ></div>
Take a closer look at UI Router's doc, there's much more you can do with it!

How To Autoload ui-view on nested views?

I have code like this
<a ui-sref="nested.something">something</a>
<div ui-view="nested.something"></div>
how to load ui-view without click ui-sref ?
EXTEND - related to this plunker provided by OP in the comments above
The state definition is:
.state('store', {
views: {
'store': {
templateUrl: 'store.html'
}
}
})
.state('store.detail', {
views: {
'store_detail': {
templateUrl: 'store_detail.html'
}
}
})
Then in this updated plunker we can see that this would do the job
//$urlRouterProvider.otherwise('/store');
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('store.detail');
return $location.path();
});
Reason? states do not have defined url. Which is a bit weird. So, I would honestly rather suggested to do it like this (the link to such plunker):
$urlRouterProvider.otherwise('/store/detail');
//$urlRouterProvider.otherwise(function($injector, $location){
// var state = $injector.get('$state');
// state.go('store.detail');
// return $location.path();
//});
$stateProvider
.state('store', {
url: '/store',
views: {
'store': {
templateUrl: 'store.html'
}
}
})
.state('store.detail', {
url: '/detail',
views: {
'store_detail': {
templateUrl: 'store_detail.html'
}
}
})
There is a working plunker
ORIGINAL
We can use the .otherwise(rule) of $urlRouterProvider, documented here
$urlRouterProvider.otherwise('/parent/child');
As the doc says:
otherwise(rule)
Defines a path that is used when an invalid route is requested.
So, this could be used for some default - start up "redirection"
The .otherwise() could be even a function, like shown here:
How not to change url when show 404 error page with ui-router
which takes '$injector', '$location' and can do even much more magic (on invalid or startup path)
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('404');
return $location.path();
});
ALSO, if we want to fill in some more details into some nested viesw, we can do it by defining multi-named views:
.state('parent.child', {
url: "/child",
views: {
'' : {
templateUrl: 'tpl.child.html',
controller: 'ChildCtrl',
},
'nested.something#parent.child' : {
templateUrl: 'tpl.something.html',
},
}
})
So, if the tpl.child.html will have this anchor/target:
<i>place for nested something:</i>
<div ui-view="nested.something"></div>
it will be filled with the tpl.something.html content
Check it in action here

Resources