Passing data in between controller without help of url? - javascript

I am creating two page webapp using AngularJS.
my Json file is:
{
"data": [
{ "name": "bhav",
"id": 123
},
{"name": "bhavi",
"id": 1234
},
{"name": "bhavk",
"id": 1235
}
]
}
my app.js(Routing file is):
myApp = angular.module('myApp', ['slickCarousel',
'ngRoute',
'myAppControllers',
'myAppServices','swipeLi'
]);
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/home-page.html',
controller: 'ProfileListCtrl',
}).
when('/profile/:typeofprofile', {
templateUrl: 'partials/profile-detail.html',
controller: 'ProfileDetailCtrl'
})
}]);
and my 1st page(home-page.html) is in given formate:
<div ng-repeat="data in data">
{{data.name}}
</div>
and on 2nd page(profile-details.html)
I want that id number of that profile considering I am using http.get request to pull data from Json file in controllers.
so please help me to fetch the id or name of clicked profile without passing through URL .
Note: I already look through ui-route link: Angular ui router passing data between states without URL but I didnt get that.

As you stated in the comments, you want to use $state.go() to pass your data.Using $state.go() to pass params is pretty simple as well. You need to inject ui.router in your application. I have created 2 partial views to show the passing of params where the params are passed from header.html to side.html.
Your JS will be something like below:
var app = angular.module('nested', ['ui.router']);
app.config(function($stateProvider,$locationProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider.state('top', {
url: "",
templateUrl: "header.html",
controller: 'topCtrl'
})
.state('top.side', {
url: '/app/:obj/:name',
templateUrl: "side.html",
controller: 'filterCtrl'
})
});
app.controller('topCtrl', function($scope,$state) {
$scope.goItem = function(){
$state.go('top.side',{obj:441,name:'alex'});
};
});
app.controller('filterCtrl', function($scope,$state) {
console.log(JSON.stringify($state.params));
$scope.params = $state.params;
});
Here is the working PLUNKER where you will find what you need to do regarding the views, controller and script:
http://plnkr.co/edit/M1QEYrmNcwTeFd6FtC4t?p=preview
I have provided the methods to pass $stateParams using both ui-sref and $state.go(). However, if you want to share the data among all the controllers. see my answer in this question:
Share Data in AngularJs

Related

Reuse Angular view and controller with different parameters

I'm working with an Angular 1 frontend, talking to a very standard REST-ish API. The general structure consists of simple HTML views with corresponding controllers talking to some base URL which usually stays the same without each controller, for example /customer in this simplified example:
Controller
app.controller('customerCtrl', function($scope, $http) {
$scope.loadCustomer = function() {
$http.get('/customer/'+$scope.id)
.then(function(response) {
$scope.customer = response.customer;
});
};
$scope.loadCustomerData = function() {
$http.get('/customer/'+$scope.id+'/data')
.then(function(response) {
$scope.customerData = response.data;
});
};
});
View
<div ng-controller="customerCtrl">
<input type="text" ng-model="id"></input>
<button ng-click="loadCustomer()">Load Customer</button>
<div>{{ customer.name }}</div>
...
...
</div>
And so on. The actual files are a few hundred lines long, each. Now all of a sudden, a new group of users are required to access the app. The frontend view and controller logic are the same, but they talk to a different backend base URL, for example /externalCustomer. The load function call would instead be to $http.get('/externalCustomer/'+$scope.id), and so on.
The views also need different URLs. If accessing the current view at http://app.com/#/customerView, the new one would be at http://app.com/#/externalCustomerView.
Given that there are many more view and controller methods like this (with a hardcoded backend URLs) and I'd rather not copy and paste a few hundred lines and have the logic diverge, what would be the proper way to implement this? It would be great to be able to reuse both the views and controllers and maybe pass some base URL parameter and/or view URL, but I'm not sure how to start.
In your routes
$routeProvider
.when('/:baseUrl', {
templateUrl: 'public/app/customerView.html',
controller: 'customerViewCtrl',
controllerAs: 'customerViewCtrl'
}
});
and in your controller inject $route and read the 'baseUrl' param as
$http.get('/'+$route.current.params.baseUrl+'/'+$scope.id+'/data')
.then(function(response) {
$scope.customerData = response.data;
});
in this way when you pass externalCustomer then that will be used for baseURL and same for customer
Another approach can be like this:
$routeProvider
.when('/customerView', {
templateUrl: 'public/app/customerView.html',
controller: 'customerViewCtrl',
controllerAs: 'customerViewCtrl',
baseUrl: 'customer'
}
}).when('/externalCustomerView', {
templateUrl: 'public/app/customerView.html',
controller: 'customerViewCtrl',
controllerAs: 'customerViewCtrl',
baseUrl: 'externalCustomer'
})
and in your controller inject $route and read the 'baseUrl' as
$http.get('/'+$route.current.baseUrl+'/'+$scope.id+'/data')
.then(function(response) {
$scope.customerData = response.data;
});

Pass Json data to another route template in angular js

After login I want to pass the user details to dashboard?How it possible in angular js?
Login.js
mySchoolApp.controller('loginController', ['$scope', '$http', function($scope, $http) {
this.loginForm = function() {
let encodedString = 'uname=' +this.username +'&pwrd=' +this.password;
sessionStorage.user = encodedString;
console.log(sessionStorage.user)
window.location.href = 'dashboard.html';
}
}]);
In console I'm getting the value.
How to get the user details in dashboard.html page?
You should use ng-route to achieve this.Angular isn't designed to work like this
Here is sample
$stateProvider
.state('app', {
abstract: true,
url: "",
template: '<ui-view/>'
})
.state('app.home', {
url: "/",
templateUrl: "partials/main_page.html",
resolve: {
skipIfLoggedIn: skipIfLoggedIn
}
}).state('app.dashboard', {
url: "/dashboard",
templateUrl: "partials/dashboard.html",
controller: 'DashboardCtrl',
activePage:'dashboard',
resolve: {
loginRequired: loginRequired
}
You can store it in a localstorage.So you can use angular-local-storage Angular module for that.
How to set :
myApp.controller('MainCtrl', function($scope, localStorageService) {
//...
function submit(key, val) {
return localStorageService.set(key, val);
}
//...
});
How to Get :
myApp.controller('MainCtrl', function($scope, localStorageService) {
//...
function getItem(key) {
return localStorageService.get(key);
}
//...
});
You should use router module ui-router or ng-router in order to use angualrjs logic in that sense but then your pages are going to be loaded via ajax and regular session http authentication can not be applied.
If that's the case then use angular service provider and let me know to edit my answer.
If you'd like to keep data across pages and not using database or server.
Then what is left as options are: sessionStorage and localStorage.
The localStorage keeps data permanently until browser cache deletes it while the other one obviously for the session.
sessionStorage.setItem('myCat', 'Tom');
If you want to keep js collection like object or array first stringify it:
var user = {pass:'moo', name: 'boo'};
sessionStorage.setItem('userDetais', JSON.stringify(user));

Angularjs with JSON, GET works but POST doesn't

I'm relatively new to angularjs. I'm trying to work with this some JSON and can't seem to figure out the issue with my post command. The get works just fine, but anything else throws a 404 url error though I checked and everything matches.
Here is my app.js code which calls the get command that works
angular
.module('app', [
'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider', function($urlRouterProvider, $stateProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'templates/home.html',
controller: 'homeCtrl',
resolve: {
friends: ['$http', function($http){
return $http.get('./api/friends.json').then(function(response ){
return response.data;
})
}]
}
})
.state('about', {
url: '/about',
templateUrl: 'templates/about.html',
controller: 'aboutCtrl'
})
.state('contact', {
url: '/contact',
templateUrl: 'templates/contact.html'
})
}])
Here is the homeCtrl.js file which loads stuff for the home page, where I want to edit the contents of the home page and post back to the JSON file.
Here I call the post and it gives me a 404 error.
angular
.module('app')
.controller('homeCtrl', ['$scope', 'friends', '$http', function($scope, friends, $http){
$scope.title = "Home";
$scope.friends = friends;
$scope.items =['item1', 'item2','item3'];
$scope.selectedValue = 'item1';
$scope.save = function() {
$http.post('./api/friends.json', friends);
};
}]);
This is the home.html
<h1>{{title}}</h1>
<ul>
<li ng-repeat = "friend in friends">
<input type="text" ng-model="friend.name">
<input type="text" ng-model="friend.age">
</li>
</ul>
<button ng-click="save()" class="btn btn-primary">Save</button>
This is the code for friends.json
[
{"name": "Will", "age": 30},
{"name": "Laura", "age": 25}
]
You said "I want to edit the contents of the home page and post back to the JSON file."
You cant save to the local files with angular. "Get" request is working just because browser can load static file (its same with css or html).
You definitely run application just by clicking html and not in any http-server. If you run server (for example nodejs http-server) in the folder and connect browser to it. It will not provide 404 (but of course it will not update json file)
If you need data to be saved, you need real working application which will provide API and process request and store data.

How to pass data from one controller to another controller in my case

I am trying to pass a data into my controller by using State Provider.
I have something like this
app.js
$stateProvider
.state('test', {
url: '/te',
views: {
'': {
templateUrl: 'test.html',
controller: 'testCtrl'
},
data:{
testValue:true
}
}
})
My controller:
app.controller('mainTestCtrl', function($scope) {
//I need to be able to get the testValue from here.
})
app.controller('testCtrl', function($scope, $state) {
var testValue = $state.current.views.data.testValue;
})
I can't really provide the state provider for mainTestCtrl because I need testValue to be true only when testCtrl is called. I need a way to pass testValue to mainTestCtrl. Is there a way to do this? Thanks.
If both controllers have the same level (a.e not parent-child) you can use $rootScope.$broadcast.
Demo 1 Fiddle
Beware!!!
be sure that 2nd controller is initialized before you send $broadcast. Otherwise noone will listen.
But I would use service that will store testValue and every controller can fetch it back:
Demo 2 Fiddle

AngularJS dynamic routing

I currently have an AngularJS application with routing built in.
It works and everything is ok.
My app.js file looks like this:
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', { templateUrl: '/pages/home.html', controller: HomeController });
$routeProvider.when('/about', { templateUrl: '/pages/about.html', controller: AboutController });
$routeProvider.when('/privacy', { templateUrl: '/pages/privacy.html', controller: AboutController });
$routeProvider.when('/terms', { templateUrl: '/pages/terms.html', controller: AboutController });
$routeProvider.otherwise({ redirectTo: '/' });
}]);
My app has a CMS built in where you can copy and add new html files within the /pages directory.
I would like to still go through the routing provider though even for the new dynamically added files.
In an ideal world the routing pattern would be:
$routeProvider.when('/pagename', { templateUrl: '/pages/pagename.html', controller: CMSController });
So if my new page name was "contact.html" I would like angular to pick up "/contact" and redirect to "/pages/contact.html".
Is this even possible?! and if so how?!
Update
I now have this in my routing config:
$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
and in my CMSController:
function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
This sets the current templateUrl to the right value.
However I would now like to change the ng-view with the new templateUrl value. How is this accomplished?
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/page/:name*', {
templateUrl: function(urlattr){
return '/pages/' + urlattr.name + '.html';
},
controller: 'CMSController'
});
}
]);
Adding * let you work with multiple levels of directories dynamically.
Example: /page/cars/selling/list will be catch on this provider
From the docs (1.3.0):
"If templateUrl is a function, it will be called with the following
parameters:
{Array.} - route parameters extracted from the current
$location.path() by applying the current route"
Also
when(path, route) : Method
path can contain named groups starting with a colon and ending with a star: e.g.:name*. All characters are eagerly stored in $routeParams under the given name when the route matches.
Ok solved it.
Added the solution to GitHub - http://gregorypratt.github.com/AngularDynamicRouting
In my app.js routing config:
$routeProvider.when('/pages/:name', {
templateUrl: '/pages/home.html',
controller: CMSController
});
Then in my CMS controller:
function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
$.get($route.current.templateUrl, function (data) {
$scope.$apply(function () {
$('#views').html($compile(data)($scope));
});
});
...
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
With #views being my <div id="views" ng-view></div>
So now it works with standard routing and dynamic routing.
To test it I copied about.html called it portfolio.html, changed some of it's contents and entered /#/pages/portfolio into my browser and hey presto portfolio.html was displayed....
Updated
Added $apply and $compile to the html so that dynamic content can be injected.
I think the easiest way to do such thing is to resolve the routes later, you could ask the routes via json, for example. Check out that I make a factory out of the $routeProvider during config phase, via $provide, so I can keep using the $routeProvider object in the run phase, and even in controllers.
'use strict';
angular.module('myapp', []).config(function($provide, $routeProvider) {
$provide.factory('$routeProvider', function () {
return $routeProvider;
});
}).run(function($routeProvider, $http) {
$routeProvider.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
}).otherwise({
redirectTo: '/'
});
$http.get('/dynamic-routes.json').success(function(data) {
$routeProvider.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
});
// you might need to call $route.reload() if the route changed
$route.reload();
});
});
In the $routeProvider URI patters, you can specify variable parameters, like so: $routeProvider.when('/page/:pageNumber' ... , and access it in your controller via $routeParams.
There is a good example at the end of the $route page: http://docs.angularjs.org/api/ng.$route
EDIT (for the edited question):
The routing system is unfortunately very limited - there is a lot of discussion on this topic, and some solutions have been proposed, namely via creating multiple named views, etc.. But right now, the ngView directive serves only ONE view per route, on a one-to-one basis. You can go about this in multiple ways - the simpler one would be to use the view's template as a loader, with a <ng-include src="myTemplateUrl"></ng-include> tag in it ($scope.myTemplateUrl would be created in the controller).
I use a more complex (but cleaner, for larger and more complicated problems) solution, basically skipping the $route service altogether, that is detailed here:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
Not sure why this works but dynamic (or wildcard if you prefer) routes are possible in angular 1.2.0-rc.2...
http://code.angularjs.org/1.2.0-rc.2/angular.min.js
http://code.angularjs.org/1.2.0-rc.2/angular-route.min.js
angular.module('yadda', [
'ngRoute'
]).
config(function ($routeProvider, $locationProvider) {
$routeProvider.
when('/:a', {
template: '<div ng-include="templateUrl">Loading...</div>',
controller: 'DynamicController'
}).
controller('DynamicController', function ($scope, $routeParams) {
console.log($routeParams);
$scope.templateUrl = 'partials/' + $routeParams.a;
}).
example.com/foo -> loads "foo" partial
example.com/bar-> loads "bar" partial
No need for any adjustments in the ng-view. The '/:a' case is the only variable I have found that will acheive this.. '/:foo' does not work unless your partials are all foo1, foo2, etc... '/:a' works with any partial name.
All values fire the dynamic controller - so there is no "otherwise" but, I think it is what you're looking for in a dynamic or wildcard routing scenario..
As of AngularJS 1.1.3, you can now do exactly what you want using the new catch-all parameter.
https://github.com/angular/angular.js/commit/7eafbb98c64c0dc079d7d3ec589f1270b7f6fea5
From the commit:
This allows routeProvider to accept parameters that matches
substrings even when they contain slashes if they are prefixed
with an asterisk instead of a colon.
For example, routes like edit/color/:color/largecode/*largecode
will match with something like this
http://appdomain.com/edit/color/brown/largecode/code/with/slashs.
I have tested it out myself (using 1.1.5) and it works great. Just keep in mind that each new URL will reload your controller, so to keep any kind of state, you may need to use a custom service.
Here is another solution that works good.
(function() {
'use strict';
angular.module('cms').config(route);
route.$inject = ['$routeProvider'];
function route($routeProvider) {
$routeProvider
.when('/:section', {
templateUrl: buildPath
})
.when('/:section/:page', {
templateUrl: buildPath
})
.when('/:section/:page/:task', {
templateUrl: buildPath
});
}
function buildPath(path) {
var layout = 'layout';
angular.forEach(path, function(value) {
value = value.charAt(0).toUpperCase() + value.substring(1);
layout += value;
});
layout += '.tpl';
return 'client/app/layouts/' + layout;
}
})();

Categories