Angular JS / data handling / overview page - angularjs

I´m developing an Angular-App. The user has to enter data on different pages whereas it´s possible to switch between the pages. Furthermore there is an "overview page" where the user can see the entered data.
So now im thinking about how to show the entered data on the overview page. Should i just use $rootScope to get the data or is it better to store it in JSON-objects or - but this is not suggested by Angular - store data in a service?
So where to get the entered data from the different pages?
Thanks!

If you want to persist data between actual HTML pages and not routes within a single page, you could use LocalStorage. Here is a service that will make that a little easier.
Another approach would be to use cookies. You can read more about using cookies in Angular here.
If you are wanting to persist the data across different routes, you will need to create a shared service. Here is an example of such an approach:
<div ng-app="myApp">
one | two
<div ng-view></div>
<script id="one.html" type="text/ng-template"><div><h1>Template One</h1>foo = {{shared.foo}}</div></script>
<script id="two.html" type="text/ng-template"><div><h1>Template Two</h1>foo = {{shared.foo}}</div></script>
</div>
angular.module('myApp', []).
config(function($routeProvider){
$routeProvider.
when('/one', {templateUrl: 'one.html', controller: 'OneCrtl'}).
when('/two', {templateUrl: 'two.html', controller: 'TwoCrtl'}).
otherwise({redirectTo: '/one'});
}).
service('sharedService', [function() {
this.foo = 'bar';
}]).
controller('OneCrtl', function($scope, sharedService){
$scope.shared = sharedService
}).
controller('TwoCrtl', function($scope, sharedService){
$scope.shared = sharedService
});
Here's a fiddle.

Related

Angular - Connecting Views to Other and/or Parent Components

I have an angular app which has a ng-view which (like any good MVC should) manipulates how the model is shown. The data (model) comes from a database, and I call it into the app's component. From there I want to propagate (if that's the right word) the model into ng-view, which loads a template to display the data based on the route. I also want to be able to filter the data/model that goes into the view with a "top-bar"
I.e:
INDEX.HTML:
<html ng-app="app">
<head>...</head>
<body ng-controller="appController">
<top-bar></top-bar>
<div ng-view></div>
</body>
</html>
APP.JS:
angular.module('app', ['top-bar','view-one','view-two', 'ngRoute']);
angular.module('app').controller('appController', function() {
var self = this;
this.myData = [];
$http.get('theQuery').then(res => self.myData = res.data);
});
angular.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/view-one', {template:'<view-one></view-one>'})
.when('/view-two', {template:'<view-two></view-two>'});
});
angular.module('top-bar', ['ngRoute']);
angular.module('top-bar').component('top-bar', {
templateUrl: './app/top-bar/top-bar.template.html',
controller: function(filterFilter) {
this.filters = filterFilter(...);
}
});
angular.module('view-one', ['ngRoute']);
angular.module('view-one').component('view-one', {
templateUrl: './app/view-one/view-one.template.html',
controller: function(filterFilter) {
// appController.data and topBar.filters would somehow
// need to be gotten from those respective modules.
this.data = appController.data;
this.filter = topBar.filters;
}
});
What I am trying to figure out is how to get the data from the main app's controller (appController) and the top-bar component, and send it to whatever view is currently loaded into ng-view.
I've been searching the web, I cannot find if the better way to do this would be to use binding (i.e. binding: {data:'<'})in the view-one controller/component, a system of $scopes, a custom service or something else. I also can't find out I would accomplish using either one to get the data in there. Thus any answers that also include a) code samples and b) links to further documentation I could read up on would be would be much appreciated.
The recommended way for doing this is to create a service, and let the different controllers work with the reference to the objects provided by the service.
Possible duplicate of enter link description here

How to reuse Angular directive in an ASP.NET MVC application?

I have an ASP.NET MVC application with a lot of Areas and models, views and controllers inside them. I have a small calculator that I want to write in Angular because it will be easier for me, as a developer, and cooler for the user (instead of using jQuery only).
The thing is I want to have this calculator on different views in some of my areas in the MVC app. The best solution that I could came up with is make an Angular directive and then use it in every view that I need it. My question is whether this will work and whether I would have to make a different Angular module for every view that will use the directive.
Any better solutions and proposals are welcome.
Example from Angular documentation: https://docs.angularjs.org/tutorial/step_07
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
you can config as many controlles that you like per page(html). and each htm will include your custom calculator directive.
All the controllers can be registered to the same module:
var phonecatControllers = angular.module('phonecatControllers', []);
phonecatControllers.controller('PhoneListCtrl', ['$scope', '$http',
function ($scope, $http) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
$scope.orderProp = 'age';
}]);
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams',
function($scope, $routeParams) {
$scope.phoneId = $routeParams.phoneId;
}]);
Here's my take on it: You don't need a separate module per view. If you are only using this to provide your calculator directive then you could just do something like:
angular.module('calculator', [])
.directive('onscreenCalculator', function () { ... });
I don't know if you are using partial views, but if you are it could be problematic if you use the ng-app = "calculator" directive at the view level. Personally, I would put it in your _Layout.cshtml and then you know you're only going to have one instance.
Your biggest challenge (in my opinion) is going to be how to get the result of the calculation back into your view since you're not truly writing an Angular app, but just using a directive. I'm sure it can be done with some playing around, though.

Reading URL Query string

I have the following URL:
http://myUrl.com/#/chooseStyle?imgUpload=6_1405794123.jpg
I want to read the imgUpload value in the query string - I'm trying:
alert($location.search().imgUpload);
But nothing alerts, not even a blank alert - but console reads:
$location is not defined
I need this value to add into a controller to pull back data, and also to carry into the view itself as part of a ng-src
Is there anything I'm doing wrong? this is my app config:
capApp.config(function($locationProvider, $routeProvider) {
$locationProvider.html5Mode(false);
$routeProvider
// route for the home page
.when('/', {
templateUrl : '/views/home.html',
controller : 'mainController'
})
// route for the caption it page
.when('/capIt', {
templateUrl : '/views/capIt.html',
controller : 'mainController'
});
}):
This is the view:
<div class="container text-center">
<h1 class="whiteTextShadow text-center top70">Choose your photo</h1>
</div>
<script>
alert($location.search().imgUpload);
</script>
Main controller:
capApp.controller('mainController', function($scope) {
$scope.message = 'Whoop it works!';
});
My end goal is that I can find a solution to capturing and re-using data from the query string.
I will also mention, this is only my first week in Angular, loving it so far! A lot to learn...
<script>
alert($location.search().imgUpload);
</script>
You're making two mistakes here:
executing code while the page is loading, and the angular application is thus not started yet
assuming $location is a global variable. It's not. It's an angular service that must be injected into your controller (or any other angular component). This should cause an exception to be thrown and displayed in your console. Leave your console open always, and don't ignore exception being thrown.
You should not do this
<script>
alert($location.search().imgUpload);
</script>
// you need to inject the module $location
//(either in service, or controller or wherever you want to use it)
// if you want to use their APIs
capApp.controller('mainController', function($scope, $location) {
$scope.message = 'Whoop it works!';
//use API of $location
alert($location.search().imgUpload);
});

Is the angular ngRoute 'Controller' declaration necessary?

After reading both the api and the developer guide, I still don't understand the functionality provided by declaring 'controller' in a given route. Right now I just have my controllers declared as ng-controller directives in my views. Is ngRoute simply providing an alternative method?
To make my question explicit in code, see below:
--Index.html
...
<body ng-app="MyApp">
<div ng-view>
</div>
</body>
--View.html
<div id="myView" ng-controller="MyController">
...
</div>
--Route.js
var app = angular.module('MyApp', [ require('angular-route') ]);
app.controller('MyController', ['$scope', function ($scope) {
console.log('this gets executed as I would expect');
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', { templateUrl: '/Index.html' })
.when('/view', { templateUrl: '/View.html' });
// below line makes no difference as an alternative to above
//.when('/view', { templateUrl: '/View.html', controller: 'MyController' });
}]);
There are two ways to define controller for a view.
Either in the controller declaration in the ng-route
in the ng-controller for the view.
Either one is fine.
You should pick one option over the other since using both will actually give you duplicate controllers, i.e. both will be used. If you're using Routes, then you can specify a few additional properties such as resolve which has been mentioned in the comments and this will allow you to perform an action, or supply supplementary data etc.
Take a look at this article, Using Resolve In Angular, for more information.
Also, you should look into using Controller As, which sets you up for future proofing. John Papa has a few blogs and videos where he praises the use of Controller As and using the var vm = this; style syntax, take a look here.
Also, as a side note, you should use the .otherwise in your routes as this will capture any requests that are invalid and at least serve up a valid page from your site. You can see this in the routeProvider documentation.

Angular $routeParams is blank

I have a really simple Angular app that I've distilled to the following:
var napp = angular.module('Napp',['ngResource']);
var CompanyCtrl = function($scope, $routeParams, $location, $resource) {
console.log($routeParams);
};
napp.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/company/edit/:id',
{templateUrl: '/partials/edit', controller: 'CompanyCtrl'}
);
}]);
and the HTML:
<div ng-controller="CompanyCtrl"></div>
When I log $routeParams, it comes up blank. When I use .otherwise(), it will load whatever I've specified there. Any idea what I'm missing?
You have a couple of errors:
You've specified the controller in two places, both in the view (<div ng-controller="CompanyCtrl"></div>) and in $routeProvider (.when('/company/edit/:id', {templateUrl: '/partials/edit', controller: 'CompanyCtrl'}). I'd remove the one in the view.
You have to register the controller in the module when specifying it in the $routeProvider (you should really do this anyway, it's better to avoid global controllers). Do napp.controller('CompanyCtrl', function ... instead of var CompanyCtrl = function ....
You need to specify a ng-view when you're using the $route service (not sure if you're doing this or not)
The new code:
var napp = angular.module('Napp', ['ngResource']);
napp.controller('CompanyCtrl', function ($scope, $routeParams, $location, $resource) {
console.log($routeParams);
});
napp.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/company/edit/:id',
{templateUrl: '/partials/edit', controller: 'CompanyCtrl'}
);
}]);
The template (/parials/edit)
<div> ... </div>
And the app (index.html or something)
... <body> <div ng-view></div> </body>
I've created a working plunker example: http://plnkr.co/edit/PQXke2d1IEJfh2BKNE23?p=preview
First of all try this with
$locationProvider.html5Mode(true);
That should fix your starting code. Then adjust your code to support non-pushState browsers.
Hope this helps!
Not sure if this helps, but I just came across this issue myself, and found that I couldn't log the route params until I had something bound to them.
So,
Router:
var myApp = angular.module('myApp', []);
myApp.config(function($routeProvider){
$routeProvider.when('/projects/:id',
{templateUrl: '/views/projects/show.html', controller: 'ProjectCtrl'}
);
});
Controller:
myApp.controller('ProjectCtrl', function($scope, $routeParams){
$scope.id = $routeParams.id;
console.log('test');
});
View:
<h1>{{ id }}</h1>
When I removed the '{{id}}' from the view, nothing was logged and $routeParams was empty, at least at the time of the controller's instantiation. As some of the answers above have pointed to, the route params are passed in asynchronously, so a controller with no bindings to that property won't execute. So, not sure exactly what you've distilled your snippet down from, but hope this helps!
This may happen (not in the OP's case) if you're using ui-router instead of ngRoute.
If that's the case, use $stateParams instead of $routeParams.
https://stackoverflow.com/a/26946824/995229
Of course it will be blank. RouteParams is loaded asynchronously so you need to wait for it to get the params. Put this in your controller:
$scope.$on('$routeChangeSuccess', function() {
console.log($routeParams);
});
It works for me http://plunker.co/edit/ziLG1cZg8D8cYoiDcWRg?p=preview
But you have some errors in your code:
Your don't seem to have a ngView in your code. The $routeProvider uses the ngView to know where it should insert the template's content. So you need it somewhere in your page.
You're specifying your CompanyCtrl in two places. You should specify it either in the $routeProvider, or in you template using ng-controller. I like specifying it in the template, but that's just personal preference.
Although not an error, you're specifying your CompanyCtrl in the global scope, instead of registering it on your Napp module using Napp.controller(name, fn).
Hope this helps!
You can always go on #angularjs irc channel on freenode: there's always active people ready to help
Could it be that your templateUrl points to an invalid template?
When you change the templateUrl to an unexisting file, you will notice that the $routeParams will no longer be populated (because AngularJS detects an error when resolving the template).
I have created a working plnkr with your code for your convenience that you can just copy and paste to get your application working:
http://plnkr.co/edit/Yabp4c9zmDGQsUOa2epZ?p=preview
As soon as you click the link in the example, you will see the router in action.
Hope that helps!

Resources