AngularJS application gathering data from multiple screens - javascript

I am working on a app that switches between different screens. Each screen collect data from the user by means of user selecting a button and clicking on it or selecting a radio button. There will be at least 5-6 screens. i need ideas on how and where to store the data collected and what's the best way to move between different screens: switch what is displayed inside a div on the page or go to an entirely different page. The data on each screen is coming from the different database tables.
So far I have one screen done - it pulls data from the database(via Web API call) and based on the data pulled, displays a different image in the hyperlink.
What I want to do is capture which hyperlink is clicked by the user and store that value somewhere(a location that will persist until all data is collected and stored in the database) and then move on to the next screen. I am sort of stuck here and need some help and ideas.
here is what i got so far:
UI for screen 1:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Types</title>
<script src="../../Scripts/angular.js"></script>
<script src="TypesCtrl.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="myController">
<h3>Select a type</h3>
<br />
<table>
<tr>
<td ng-repeat="Type in Types">
<img src="Images/type1.png" ng-show="Type.TypeId=='1'" />
<img src="Images/type2.png" ng-show="Type.TypeId=='2'" />
<img src="Images/type3.png" ng-show="Type.TypeId=='3'" />
<img src="Images/type4.png" ng-show="Type.TypeId=='4'" />
</td>
</tr>
</table>
</div>
</body>
</html>
and here is my angular controller:
(function () {
angular.module("myApp", []).controller("myController", TypeCtrlFunction);
TypeCtrlFunction.$inject = ["$scope", "$http"];
function TypeCtrlFunction($scope, $http) {
$http.get('http://localhost:49358/api/myAPI/GetTypes').
then(function (result) {
$scope.DeviceTypes = result.data;
});
};
})();
I'd appreciate some help to get me moving forward

You can share data between the different states/controllers either by setting up a service or by using rootScope. Typically it is better practice to use a service. Then you can change views using uiRouter. An example for setting up states:
app.config(['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/main");
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'main.html'
})
.state('main.mainstuff', {
url: '/mainstuff',
templateUrl: 'mainstuff.html'
})
.state('main.secondstuff', {
url: '/secondstuff',
templateUrl: 'secondstuff.html'
});
}]);
Here is a plunker showing how implement using nested states. This example uses rootScope but you should consider using a service as AndyHasIt mentioned.

You coude use ui-routing for swithing between different views. As for storing data there are two ways i would do it. One is using services to store values or you could also use local storage or cookies in browser for the same

To share data between controllers, use a service:
app = angular.module('MyApp', []);
app.service('SharedDataService', function() {
return {
someVar: 'hello'
}
})
app.controller('Controller1', function(SharedDataService, $scope) {
$scope.value1 = SharedDataService.someVar;
})
app.controller('Controller2', function(SharedDataService, $scope) {
$scope.value1 = SharedDataService.someVar; //The same value
})
To load different pages within the same page I suggest you use ngRoute or uiRouter

Related

Can an Angular controller bind to multiple parts of a web page?

Suppose that I've written a web page that requires the user to key in data into forms. Suppose that there are two parts of the page that are completely separate in the DOM, yet are logically related. I need to bind them to a single model.
The first (bad) solution I can think of is to completely restructure the page so that everything to be bound to the model is contained in a single <div> element (or perhaps even put the controller on the <body> element).
Another solution might be to bind the inputs to a object that could be made a member of two different controllers, but that sounds like a bit of a kludge.
Suppose the HTML looks like this:
<input ng-model='data1' />
<div>
<!-- something complicated -->
</div>
<input ng-model='data2' />
You can create a shared service and inject into both controllers. This can be achieved by either the factory or service pattern. See SO post angular.service vs angular.factory for some insight on the difference/similarity between the two.
This is the Angular way to do this. See the AngularJS services docs for more information. A simple example may include...
<div ng-app="app">
<div ng-controller="ctrlA"></div>
<div ng-controller="ctrlB"></div>
</div>
app.service('sharedService', [function () {
this.someValue = 'yo!'
}]);
app.controller('ctrlB', ['$scope', 'sharedService', function($scope, sharedService) {
console.log(sharedService.someValue) // yo!
}]);
app.controller('ctrlA', ['$scope', 'sharedService', function($scope, sharedService) {
console.log(sharedService.someValue) // yo!
}]);
JSFiddle Link

How to hide show in Angular

I am beginner in angular js
HTML
<div ng-app="myapp">
<div ng-controller="maincontrol">
<div ng-show="!vis">show</div>
<div ng-show="vis">hide</div>
</div>
<div ng-view></div>
</div>
JS
var app = angular.module('myapp', ['ngRoute'])
app.controller('maincontrol', function ($scope) {
$scope.vis = true;
$scope.fun = function () {
if ($scope.user == "home" && $scope.pass == "home") {
console.log($scope.user, $scope.pass);
$scope.vis = false;
}
}
})
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'home.html'
})
.when('/contact', {
templateUrl: 'contact.html'
})
});
and also i have two html pages like
home.html
<div ng-controller="maincontrol">
<input ng-model="user"/>
<input ng-model="pass"/>
<div ng-click="fun()">
click
</div>
</div>
contact.html
<div>
contact
</div>
my expectation is after entering home into user and pass. if i click 'click' i need to show 'show' label instead of 'hide'. pls help me.
Each controller has its own scope, when you wrote $scope.vis=false on fun(), you actually created a new variable on maincontroler1 scope. If you expected this variable to affect the view which is binded to maincontroler scope, it won't happen.
I suggest 2 options:
You can use one controller for entire app (If you use same controller in two tags it will still create a new scope although it is the same controller), this way the fun() method that was called from the first view will change the boolean in the single controller and will affect the second view. Please note when you use ng-view you will have to get the variable from the parent.
So I used this code:
$parent.user
$parent.pass
Create this working plunker for you.
Share the vis boolean between 2 controllers using a service. You can
use this post for this option.
You can also use reach parent controller scope from child controller, that can be done if ng-view will be nested in the outer controller. You can use this post for option 3.

Updating model variable upon navigation

Why isn't {{ username }} variable (in example below) updated when I'm navigating using in-page links? The variable is only set on initial page load (equal to Anonymous) and isn't updated no more, why is that? Code i plain and simple (http://jsbin.com/OTApeYI/1/):
<!doctype html>
<html lang="en" ng-app="examp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"> </script>
</head>
<body ng-controller="ExampleCtrl">
Home, Admin
Your user name is: {{ username }}
<script>
angular.module('examp', ['examp.controllers']).
config(function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider.when('/:username', {controller: 'ExampleCtrl'});
$routeProvider.otherwise({redirectTo: '/'});
});
angular.module('examp.controllers', [])
.controller('ExampleCtrl', ['$scope', '$routeParams', function($scope, $routeParams) {
$scope.username = $routeParams.username ? $routeParams.username : "Anonymous";
}]);
</script>
</body>
</html>
First, I think you need the ngView directive to activate routing. Second, ExampleCtrl is only created once and you are setting $scope.username to the current value at that time. $routeParams.username is a simple string, you might as well set $scope.username = '' You can however store the $routeParams object on your scope and bind to the username property (SAMPLE). I also disabled html5 or I don't think it works with jsbin.
<div ng-view></div>
<p>Your user name is: {{ username }}</p>
<p>params.username is: {{ params.username }}</p>
<p>eventusername is: {{ eventusername }}</p>
<p>JSON:</p><pre>{{ params|json }}</pre>
And in your controller:
$scope.params = $routeParams;
Another option would be to look for route change events and handle them:
$scope.$on("$routeChangeStart", function(event, next, current) {
$scope.eventusername = next.params.username;
});
Because you're always using the 'ExampleCtrl' controller, you're only ever reading the $routeParams once. The $routeParams object is only created the one time that the controller is created. It doesn't update dynamically. So even though your route may have changed from say /macadamia to /macadamia123, the $routeParams object is still the same as it was when the controller was created for your /macadamia route (so $routeParams.username still equals '/macadamia'). You need to reload the controller in order to read the $routeParams again.
I've wanted the $routeParams object to be dynamic for a long time, but unfortunately angular's $routeProvider doesn't work that way.

Global "App" controllers in AngularJS

I have noticed in a few tutorials and code examples floating around the internet developers using a global AppController in their applications and modules.
Is it best practice to create a global AppController in AngularJS?
I do see some benefits such as being able to handle events in a "global" scope such as:
app.controller('AppController', function($scope, $rootScope, $route, $location){
$rootScope.$on('$routeChangeStart', function(event, current, previous) {
console.log('Do something...');
});
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
console.log('Do something...);
});
});
are there any other advantages or disadvantages to this pattern?
Purely in context of situation. Let's take an example of dynamically changing title tags and page view:
.config(['$routeProvider','$locationProvider',function($routeProvider,$locationProvider){
$routeProvider.when('/', {
template: '/views/home.html',
title:'Home'
});
$locationProvider.html5Mode(true);
}]);
.controller('app', ['$scope','$route','$location',function($scope,$route,$location){
$scope.$on("$routeChangeSuccess",function($currentRoute,$previousRoute ){
$scope.title = $route.current.title;
$scope.page = $route.current.template;
});
}]);
Now both our title and page view are being dynamically loaded in through app level controller that wraps our application. This can be very useful.
<html lang="en" ng-controller="app">
<head>
<title>{{title}}</title>
</head>
<body>
<ng-include src="page"></ng-include>
</body>
</html>
Here's an example of when not to use it. Let's say one of our partial pages return data from an API:
<!-- search.html -->
<div ng-repeat="item in items">
{{item.title}}
</div>
And in our app level controller we are pulling data via broadcast:
$scope.$on('searchComplete',function(d){
$scope.items = d
});
That partial will show the data as we intended however - problems could arise when other child partials use items where scope is being overwritten.
<!-- other-search.html -->
<div ng-controller="OtherSearch" ng-click="search()">
<div ng-repeat="item in items">
{{item.title}}
</div>
</div>
In this partial, ng-click is guiding the users request. So if the app level controller already binded items in the parent, the user will see a list of items when toggling to this partial even if they never triggered the action of search().

Index page separate from rest of AngularJS app?

I'm working on two projects right now using AngularJS, and I'm running into the same problem with both of them.
The problem is that I have an index page that looks completely different from any of the inner pages, which means that my ng-view has to consist of the entire page. This makes it so that any time a route changes, the whole page has to reload instead of just the main content area. This causes things like the header or sidebar to flash briefly.
The only good approach I can think of to make my index page separate from my app is to literally have a separate, static index.html and then all my angularJS pages inside a separate folder so that I can use a more focused ng-view.
Is this the only/best approach there is? Has anyone achieved this, or have any ideas on how to? thanks.
A way to solve this problem would be using UI-Router.
For example:
You could have an app.html which is a page that holds all of your application views. In it add a:
<body>
<div ui-view></div>
</body>
and styles/scripts required by the entire application.
All of your views will go there including the index.html view.
Assuming that the pages except the index have some sort of header/body/footer layout in which the body changes according to the actual page you can use a configuration as follows:
var app = angular.module('app', [])
.config(['$stateProvider', function ($stateProvider)
{
$stateProvider
.state('index', {
url: '/index',
templateUrl: 'index.html',
controller: 'IndexController'
})
.state('root', {
templateUrl: 'root.html',
controller: 'RootController'
})
.state('root.somePage', {
url: '/some-page',
templateUrl: 'some-page.html',
controller: 'SomePageController'
})
.state('root.anotherPage', {
url: '/another-page',
templateUrl: 'another-page.html',
controller: 'AnotherPageController'
});
}
The root.html will be like a masterpage in ASP.NET Webforms so it would be in the form:
<!-- header markup here -->
<div ui-view></div>
<!-- footer markup here -->

Categories