AngularJS reuse multiple controllers to build a webapp - angularjs

What I'm looking for is to learn a proper way to build a webapp. I already built some things, but I've got to a point where I need to reuse some data and with ng-controllers, it's getting harder.
I already know controllers are not the best option, so I tried to jump to directives, based on some articles I've read. But none of them has helped me.
So, let me try to describe it.
Description
I'm building a dashboard, where i have some clients (add/edit/del), projects (which invole one or more clients), agenda, configuration, financials, etc..
I've built a lot of things already, but for example:
On the home page I'm displaying a table with the last 5 clients added to the app, also a table with the last 5 projects added to the app. Then, on the clients.html page, I display the whole table, same goes for projects, on the project.html. Both with just 3-4 fields with name, tel and email. Then on the individual client page, i display the whole information about that client. Such as address, email, contacts, observations, etc. And also a list of projects he is involved.
So what I have is something like this:
app.js
myApp.controller('ClientesCtrl', function ($scope, $http, $routeParams) {
$scope.pagename = "Clientes";
$scope.get_cliente = function() { //Function - Get Cliente
$http.get("scripts/data/clientes.json")
.success( function(data) {
$scope.pagedClientes = data;
})
.error(function(data) {});
};
$scope.add_cliente = function() { //Function - Add Cliente
$scope.formprevent = true;
$http.post('scripts/php/db.php?action=add_cliente',
{
'cod': $scope.cad.cod,
[... more data ...]
}
)
.success(function (data, status, headers, config) {})
.error(function (data, status, headers, config) {});
};
});
Same goes for projects, each one with it's controller.
My folder/File organizations is very very simple (since I don't know what I can put in different files, or even how to call it back). It's something like this:
-index.html
-scripts
--js
---angular.min.js
---angular-route.min.js
--app
---app.js
-content
--home.html
--clients.html
--projects.html
The Problem
The problem starts when i need to show those data in a lot of pages.
For example in the home page, i have a list with a resume of the main data, such as total clients, total projects, and it's like this:
<div class="col-md-3" ng-controller="ClientesCtrl">
<div ng-init="get_cliente();>
<div class="label">{{pagedClientes.length || "00"}}</div>
<div class="text">clientes totais</div>
</div>
</div>
<div class="col-md-3" ng-controller="ProjectsCtrl">
<div ng-init="get_projects()">
<div class="label">{{pagedProjects.length || "00"}}</div>
<div class="text">Processos totais</div>
</div>
</div>
<div class="col-md-3">
<div>
<div class="label">00</div>
<div class="text">Processos abertos</div>
</div>
</div>
<div class="col-md-3">
<div>
<div class="label">00</div>
<div class="text">Compromissos abertos</div>
</div>
</div>
<div class="table-body" ng-controller="ClientesCtrl">
<table ng-init="get_clients()">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="client in pagedClients | limitTo:-5 | orderBy:'-id'" ng-if="pagedClients.length > 0">
<td>{{cliente.cod}}</td>
<td>{{cliente.nm_client}}</td>
<td>
<a class="bt-t bt-inf" href="#/detcliente/{{cliente.id}}"></a>
</td>
</tr>
<tr ng-if="pagedClientes.length == 0">
<td colspan="3"><h3>No client</h3></td>
</tr>
</tbody>
</table>
</div>
<div class="table-body" ng-controller="ProjectsCtrl">
<table ng-init="get_projects()">
<thead>
<tr>
<th>ID</th>
<th>Project</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="project in pagedProjects | limitTo:-5 | orderBy:'-id'" ng-if="pagedProjects.length > 0">
<td>{{project.cod}}</td>
<td>{{project.nm_cliente}}</td>
<td>
<a class="bt-t bt-inf" href="#/detproject/{{project.id}}"></a>
</td>
</tr>
<tr ng-if="pagedClientes.length == 0">
<td colspan="3"><h3>No project</h3></td>
</tr>
</tbody>
</table>
</div>
So, basically, I need to add the controller in each block I need to display that data, also I have to 'init' the function to get the data again. This is a simple example, but I think it was enough to show what I need to solve.
It's worse when I need to show the individual client, with only their projects. So before I get crazy with all of those controllers, I want to know how is the best way to put up the logic, the folder/file organization, the code organization. Is it better to use a directive? to make the directive call a controller? Call multiple controllers? Or what?

You need to use services to fetch the data: https://docs.angularjs.org/guide/services. For your code it would look something like this:
app.factory('clients', function ($http) {
var getClients = function() { //Function - Get Cliente
return $http.get("scripts/data/clientes.json")
.success( function(data) {
return data;
})
.error(function(data) {});
};
var add_cliente = function(cad) { //Function - Add Cliente
$http.post('scripts/php/db.php?action=add_cliente',
{
'cod': cad.cod,
[... more data ...]
}
)
.success(function (data, status, headers, config) {})
.error(function (data, status, headers, config) {});
};
return {
getClients: getClients,
add_cliente: add_cliente
}
})
You can then inject the service in a controller and use the functions in your controller:
app.controller('Ctrl', function (clients, $scope) {
clients.getClients().then(function (data) {
$scope.myClients = data;
});
});

Read the client data on initialization of the controller - not need to use a ng-init.
myApp.controller('ClientesCtrl', function ($scope, $http, $routeParams) {
$scope.pagename = "Clientes";
$http.get("scripts/data/clientes.json")
.success( function(data) {
$scope.pagedClientes = data;
})
.error(function(data) {});
$scope.add_cliente = function() { //Function - Add Cliente
$scope.formprevent = true;
$http.post('scripts/php/db.php?action=add_cliente',
{
'cod': $scope.cad.cod,
[... more data ...]
}
)
.success(function (data, status, headers, config) {})
.error(function (data, status, headers, config) {});
};
});
Controllers can be nested. Define the controller on a div which wraps the area where you need the client data. Same for the ProjectsController. You could even merge the 2 controllers in one.
<div ng-controller="ClientesCtrl">
<div class="col-md-3" >
<div ng-init="get_cliente();>
<div class="label">{{pagedClientes.length || "00"}}</div>
<div class="text">clientes totais</div>
</div>
</div>
....

Related

Selecting default value using ngModel ngRepeat, ngOptions

Hopefully someone can help.
I am developing an application using HTML AngularJs which uses ng-repeat,ng-options and ng-model and populates multiple rows based on the data in the database for a user. Each row has static data coming from DB (returned as object via restAPI) and dynamic select option for user selection. Select option is hardcoded in app.js and linked to model on HTML for DB update upon selection using update button. Each row has its own button and i can see update function is working at row level.
I want to set the default value of the drop down list dynamically as value of an element coming from database. Object is same as one being used to populate rows with static data .
Code is in the fiddle at https://jsfiddle.net/6j88L61y/4/
HTML below
<body>
<h1 align="center">User Tracker</h1>
<div ng-controller="MainController as main">
<div>
<p>Please Enter ID </p>
<p>
<input type="text" ng-model="main.model.userName"></input>
<button ng-click="main.model.getOrgList()">List State List</button>
</p>
</div>
<hr ng-show="main.model.formSubmitted"></hr>
<div>
<table class="table table-bordered" border="1">
<thead>
<tr>
<th>ID</th>
<th>User Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="org in main.model.orgList" id="{{org.id}}">
<td>{{org.id}}</td>
<td align="center">{{org.user}}</td>
<td align="center">
<select ng-model="main.model.selectedRecord.appCurrentStateSelected[$index]" ng-options="option.value as option.value for option in main.model.appCurrentStateList" ></select>
</td>
<td>
<button ng-click="main.model.updateAppDetailsList({id:org.id,userName:org.name,appCrntState:main.model.selectedRecord.appCurrentStateSelected})">Update</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
JS
"use strict";
angular.module('myApp',[]);
angular.module('myApp').service('AppModel', function( $http) {
this.userId='';
this.userName ="";
this.formSubmitted="";
this. selectedRecord ={appCurrentStateSelected:''};
this.appCurrentStateList =[{name: 'New',value:'New',id:1}, {name: 'InUse',value:'InUse',id:2},{name: 'Inactive',value:'Inactive',id:3},{name: 'Deleted',value:'Deleted',id:4}];
this.submittedAppDetailsList=[];
console.log(' json sample:'+this.submittedAppDetailsList);
var path = 'home';
var currentProtocol = location.protocol;
var host =location.host;
var apiHost = currentProtocol+'//'+host+'/api/';
console.log('API url is : ' +apiHost);
// Get method
this.getOrgList = function() {
var path = 'home/userid';
console.log(this.userName);
console.log(this.selectedRecord);
$http.get(apiHost+path+'/'+this.userName+'/')
.then(function(response) {
this.orgList =response.data;
this.formSubmitted = true;
console.log(response.data);
}.bind(this),
function(response) {
console.log(response.data);
});
}
// Post method
this.updateAppDetailsList = function(appdetailsList) {
var path = 'home/update';
console.log(this.selectedRecord);
$http.post(apiHost+'home/update/',appdetailsList)
.then(function(response) {
this.submittedAppDetailsList.push(response.data);
this.formSubmitted = false;
console.log(response.data);
}.bind(this),
function(response) {
console.log('Error : '+response.data);
});
}
});
angular.module('myApp').controller('MainController', ['AppModel', function (AppModel) {
this.model = AppModel;
}]);

Angular JS ng-repeat not displaying values

I am making an REST call from angular to Spring . I am able to get the response back .When i am trying to populate the values in the view using ng-repeat , nothing is shown on the screen .
This is my Angular Code This code is inside the showhidecontroller
var resuls = $http.post('http://localhost:8080/aeservices/AddConfig', dataobj);
resuls.success(function(data, status, headers, config) {
$scope.dbresponse= data;
$scope.messagetest = $scope.dbresponse[0].messages;
alert($scope.messagetest);
console.log( $scope.messagetest);
console.log(data);
});
This is my Response i recieved from API
[{
"data12": null,
"name": null,
"errors": ["error data1", "error data2"],
"messages": ["Configuration has been Added successfully", "Configuration has been Added successfully"]
}]
This is my HTML
<table ng-controller="ShowHideController">
<tr ng-repeat="item in dbresponse[0].errors" >
<span><td align="left" class="validationMsg"><img src="images/red_bullet.gif" border="0" width="8" height="8" alt="">&nbsp
{{item}}
</td></span></tr>
</table>
I tried using ng-repeat by declaring myself an item like this $scope.items = ['one','two','three','four']. Even this is not showing up on the HTML.
Try using data.data,
Controller:
app.controller("listController", ["$scope", "$http",
function($scope, $http) {
$http.get('test.json').then(function(response) {
$scope.dbresponse = response.data;
});
}
]);
HTML:
<table ng-controller="listController">
<tr ng-repeat="item in dbresponse[0].errors">
<td align="left" class="validationMsg"><img src="images/red_bullet.gif" border="0" width="8" height="8" alt=""> {{item}}
</td>
</tr>
</table>
DEMO
Please try this below code and don't declare variable resuls.
$http.post('http://localhost:8080/aeservices/AddConfig', dataobj).success(function(data, status, headers, config) {
$scope.dbresponse= data;
$scope.messagetest = $scope.dbresponse[0].messages;
alert($scope.messagetest);
console.log( $scope.messagetest);
console.log(data);
});
The Problem that happened was i have declared my controller twice in the HTML

Angular 1.5 SharePoint, only show selected department

I have have made a small Angular employee phone book app from a SharePoint list. The app is based on among other tutorials:
http://ramdotnetdeveloper.blogspot.no/2016/05/sharepoint-2013-filtering-and-sorting.html
While the scope.sortExpression does its job sorting on lets say title, department, manager and so on....I would like since there are subdepartments be able to add those as options to the dropdown and only show those results.
So if i chose department DEP I 1, it will only show persons belonging to this department, DEP I 2 and so on is it possible through some sort of filtering?
var app = angular.module('ansattApp', ['angularUtils.directives.dirPagination']);
app.controller('ansattController', function ($scope, $http) {
$http({
method: 'GET',
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('Telefonkatalog')/items?$top=1000",
headers: { "Accept": "application/json;odata=verbose" }
}).success(function (data, status, headers, config) {
$scope.ansatte = data.d.results;
$scope.mySortFunction = function(ansatt) {
//Sorting Item
if (isNaN(ansatt[$scope.sortExpression]))
return ansatt[$scope.sortExpression];
return parseInt(ansatt[$scope.sortExpression]);
}
}).error(function (data, status, headers, config) {});
});
HTML
<div data-ng-app="ansattApp" class="row">
<div data-ng-controller="ansattController" class="span10">
<div class="form-group">
<div>
<h5>Sorter etter: </h5>
<select ng-model="sortExpression" class="form-control">
<option value="Title">Tittel</option>
<option value="Seksjon">Seksjon</option>
</select>
</div>
<input type=text" data-ng-model="search" placeholder="Søk etter ansatte,seksjon m.m." class="form-control"/>
<h1>{{search }}</h1>
<table class="table table-striped table-hover">
<tbody>
<tr>
<th>Etternavn</th>
<th>Fornavn</th>
<th>Tittel</th>
<th>Enhet</th>
<th>Kontor</th>
<th>Arbeid</th>
<th>Mobil</th>
</tr>
<tr dir-paginate="ansatt in ansatte | filter:search | orderBy:mySortFunction | itemsPerPage:25">
<td>{{ansatt.Etternavn}}</td>
<td>{{ansatt.Fornavn}}</td>
<td>{{ansatt.Title}}</td>
<td>{{ansatt.Seksjon}}</td>
<td>{{ansatt.Kontornummer}}</td>
<td>{{ansatt.Arbeid}}</td>
<td>{{ansatt.Mobil}}</td>
</tr>
</tbody>
</table>
<dir-pagination-controls
max-size="500"
direction-links="true"
boundary-links="true"
on-page-change="data.getData(newPageNumber)" >
</dir-pagination-controls>
</div>

bootstrap-table not rendering upon updating model in Angular

Hi I am not able to render table using bootstrap-table and angular. here is my code, I think I need to call bootstrap-table init method in angular ajax call. Can some one guide me on how to do this..?
angular
.module('reports')
.controller(
'ReportCtrl',
[
'$scope',
'$http',
'ngProgress',
function($scope, $http, ngProgress) {
var vm = this;
vm.mdp = {};
vm.mdp.data = [];
vm.mdp.columns = [];
$scope.submit = function() {
var report = $scope.tab;
$http.post('/reports/cmd/getData', {
report : report,
date : createdAfter
}).success(function(data) {
vm.mdp.data = data;
$.each(data[0], function(key, value){
vm.mdp.columns.push(key);
});
}).error(function(error) {
alert(error);
});
};
} ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="mdp" class="panel" ng-controller="ReportCtrl as report" ng-show="panel.isSelected('mdp')">
<table data-toggle="table" data-show-columns="true" data-search="true" data-show-export="true" data-pagination="true" data-height="299">
<thead>
<tr>
<th ng-repeat="c in report.mdp.columns" data-field= {{c}} >{{ c }}</th>
</tr>
</thead>
<tr ng-repeat="r in report.mdp.data">
<td ng-repeat="c in report.mdp.columns">{{ r[c] }}</td>
</tr>
</table>
</div>
Integrating Bootstrap Table with Angular is solved here:
https://github.com/wenzhixin/bootstrap-table/issues/165
https://github.com/AkramKamal/bootstrap-table-examples/tree/master/integrate
I have some minor changes in my implementation of this solution which I will upload to Github / JSFiddle shortly. But the links above will allow you to get going.

Displaying Json Data from ng-repeat in multiple containers

Hey I have a question about using ng-repeats. I'm trying to display user data from a large json file in two separate containers. When a user clicks on a row it displays the other piece of the ng-repeat in a different section. If someone could take a look at this fiddle and maybe give me a direction to go in that would be awesome. Thanks!
I'm also using ngTable for the table params, but I don't think that has much to do with the issue.
http://jsfiddle.net/cL5aE/1/
HTML:
<body>
<div ng-controller="myController">
<div class="col-md-6">
<table>
<tr ng-repeat="user in $data" ng-click="loadDetails()">
<td>{{user.name}}</td>
<td>{{user.id}}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<tr ng-repeat="user in $data" ng-show="loadDetails()">
<td>{{user.foo}}</td>
<td>{{user.bar}}</td>
</tr>
</div>
</div>
</body>
Controller:
angular.module('app', ['ngTable']);
app.controller('myController', function ($scope, $http, ngTableParams) {
$http.get('http://myjson.com/data.json')
.success(function (data, status) {
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
CompleteDate: 'asc' // initial sorting
}
}, {
total: data.length, // length of data
getData: function ($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ? $filter('orderBy')(data, params.orderBy()) : data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
$scope.loadDetails = function(data) {
//???
}
});
I would pass the user object as a parameter to a function and assign it a model. That way you don't need to use the ng-repeat in both sections leading to a cleaner and more readable code.
Pass the object you're displaying on the ng-repeat:
<tr ng-repeat="user in $data" ng-click="loadDetails(user)">
Function to load the object to a model property:
$scope.loadDetails = function(user) {
$scope.viewModel.selectedUser = user;
}
And finally assign the model property to the view:
<table>
<tr ng-show="viewModel.selectedUser">
<td>{{viewModel.selectedUser.foo}}</td>
<td>{{viewModel.selectedUser.bar}}</td>
</tr>
</table>
http://jsfiddle.net/jimenezjrs/5Cd32/

Resources