I'm new to AngularJS and I don't know how to accomplish a task. In my system I have a database with two tables: "Customers" and "Offices". This is a 1:N relation. In my HTML page I have a list (actually is a table) that contains info about the customers (info extracted from the "Customers" table). For each row of the table, you can find a button. If you click on that button some infos about the offices of THAT customer are loaded from the database.
The first part is quite simple. This is the Angular service that loads customers info:
angular.module("app").factory("Customer", ["$resource",
function($resource){
return $resource("/customers/list",
{format:'json'},
{
find: {
method:'GET'
}
});
}]);
This is the Angular controller that exposes an array of customers:
angular.module("app").controller("customersController", ["Customer", "$scope",
function (Customer, $scope){
var customers = new Array();
var metacustomers = Customer.find(function(){
for(var i=0; i<metacustomers.results.length; i++){
customers[i] = new Object();
customers[i].customerName = metacustomers.results[i].customer_name;
customers[i].customerID = metacustomers.results[i].customer_ID;
}
$scope.customers = customers;
});
}]);
And this is the part of the view that shows info:
<table>
<thead>
<th></th>
<th></th>
<th></th>
</thead>
<tr data-ng-repeat="customer in customers | filter:query">
<td>
+
</td>
<td>
<strong>{{customer.customerName}}</strong>
</td>
<td>
<div>
<a title="Modify customer" href="/customers/post/{{customer.customerID}}">
</a>
<a title="Delete customer" href="/customers/delete/{{customer.customerID}}">
</a>
</div>
</td>
</tr>
</table>
All of this looks like:
The problem arrives with the second task. When I click on the "+" button I must load the offices infos about THAT customer (the customer on the same row of the button). I need the customerID to retrieve these infos and I have it. But, how can I say to Angular to load exactly the info belongs to the right customer? I don't know how to model this situation. I need your help. Thank you in advance.
You can pass the customer to the ng-click directive like so:
+
And then create an expand function in your controller which takes a customer as its input. Something like this:
$scope.expand = function(customer){
//fetch the customer
};
Related
I am trying to dynamically add a dropdown using $sce.trustAsHtml() function but I am getting an empty list in the UI. Here is the code:
$scope.addRowtrain = function() {
$scope.locomotivesList = [{"name": "loco1", "value":"1"}, {"name": "loco2", "value":"2"}];
tableData[id] = $sce.trustAsHtml('CTRun'+counter++);
tableData[type] = $sce.trustAsHtml("<select data-ng-model='selectedLoco' data-ng-options='loco.name for loco in locomotivesList'></select>");
}
In the HTML, I want to render it as a table:
<table>
<tbody>
<tr ng-repeat="data in tableData track by $index">
<td ng-repeat="(k, p) in data track by $index"><span ng-bind-html=p>{{p}}</span></td>
</tr>
</tbody>
<a class="btn btn-danger" ng-click="addRowtrain()">Add Run</a>
...
</table
but it is displaying an empty table, please help
you are adding it dynamically you must not pass binding values instead pass Complete JSON object.
It's working with
this example
md-select in angular material
Update
Problem:
Let me try to explain what I want in one or two lines, In Demo 1 where I've used Angular Datatables when I click on Edit button the data DOES NOT appear in Edit form, whereas in Demo 2 I haven't used any datatables but the data is clearly appearing in edit form, I want the data to appear in Demo1 using Datatables. The data is inside the $scope.update but for some reasons it is not appearing in HTML whereas using the same HTML It works perfectly without datatables.
Demo1: http://plnkr.co/edit/EXXbkPUHfxcZ3blzvMaz?p=preview
Demo2: http://plnkr.co/edit/QYZzmJNwWTQaIgvUkRzQ?p=preview
Background
Initially on the left hand side the Data is inserted from a form which contain one Input type and one Select (Colony Type), there are two forms Insert, Update form on the left hand side one form is for insertion and one for editing, when the insertion form is visible the edit form is hidden and vice versa, on the right hand side the list of data is displayed with the help of datatables along with Edit and Delete button, Important thing is the buttons are made inside the DataTable code and not on HTML page, now Delete and Insert works absolutely fine, but Edit !! No it doesn't.
Problem
Case 1: (When I use Datatables)
when the Edit button (CODED INSIDE DATATABLES) is clicked an ID is sent, In the Below picture the Id is consoled "47" then an $http request is made which brings the Data and printed in console. but when I try to inject the values back to Update form it doesn't work, although when I consoled $scope the values are injected into update object but not printing on HTML page.
Case 2: (When I don't Use Datatables)
If I don't use Datatables and click the Edit the button every thing works absolutely fine and the data is injected into update object and printed on HTML page.
HTML PAGE:
If DataTables are Used
<!-- IF DataTables are Used For printing the Data on Right Side-->
<div ng-controller="colony_Controller as Main_Module">
<table class="table table-striped table-bordered" align="center" datatable="" dt-options="Main_Module.dtOptions" dt-columns="Main_Module.dtColumns" class="row-border hover">
</table>
If DataTables are NOT Used
<!-- If DataTables are NOT Used for Printing the Data on Right Side -->
<table class="table table-striped table-bordered">
<thead>
<tr>
<th style="width: 323px;" aria-label="">Colony Name</th>
<th style="width: 170px;" aria-label="">Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="colony in es_colony_details" >
<td style="width: 323px;" aria-label="">{{colony.es_colony_name}}</td>
<td>
<button ng-click="EditColonyData(colony.es_colony_id)" class="btn btn-primary">
<i class="icon-edit"></i> Edit</button>
<button ng-click="DeleteColonyData(colony.es_colony_id)" class="btn btn-danger">
<i class="icon-remove icon-white"></i> Delete</button>
</td>
</tr>
</tbody>
</table>
Controller
Main_Module.controller('colony_Controller', function colony_Controller($window, $scope, $http, bootbox, $compile, DTOptionsBuilder, DTColumnBuilder, SimpleHttpRequest, DelMainRecPicRecUnlinkPic, message)
{
$scope.field = {};
$scope.update = {};
var dtInstance = {};
/********************************** FETCH DATA START *******************************/
$http.get('http://localhost:3000/api/SELECT/es_colony_type').success(function successCallback(data)
{
$scope.es_colony_type = data.es_colony_type;
//console.log(data.es_colony_type);
});
// ONLY USED WHEN Datatable are NOT
//$http.get("http://localhost:3000/api/SELECT/es_colony").success(function successCallback(data)
//{
// $scope.es_colony_details = data.es_colony;
// console.log(data.es_colony);
//});
/********************************** FETCH DATA END *********************************/
/********************************** DISPLAY DATA START *******************************/
var vm = this;
vm.dtOptions = DTOptionsBuilder
.fromFnPromise(function()
{
return $http.get('http://localhost:3000/api/SELECT/es_colony')
.then(function(response)
{
return response.data.es_colony;
});
})
.withOption('order', [0, 'desc'])
.withDisplayLength(5)
.withPaginationType('simple_numbers')
.withOption('createdRow', function(row, data, dataIndex)
{
$compile(angular.element(row).contents())($scope);
})
vm.dtColumns =
[
DTColumnBuilder.newColumn('es_colony_name').withTitle('Colony'),
DTColumnBuilder.newColumn(null).withTitle('Actions').notSortable().withOption('width', '31%')
.renderWith(function(data, type, full, meta)
{
return '<button class="btn btn-primary" ng-click="EditColonyData(' + data.es_colony_id + ');">' +
'<i class="icon-edit"></i> Edit' + '</button> ' +
'<button class="btn btn-danger" ng-click="DeleteColonyData(' + data.es_colony_id + ');">' +
'<i class="icon-remove icon-white"></i> Delete' + '</button>';
})
];
$scope.EditColonyData = function(id)
{
console.log(id);
$http.get('api/SELECTBYID/es_colony/es_colony_id/'+id)
.success(function(data)
{
console.log(data);
console.log($scope);
$scope.YesEdit = true;
$scope.update = data.es_colony[0];
// **This is where I'm injecting data Back to $scope object**
$scope.update.es_colony_type_id = data.es_colony[0].es_colony_type_id;
});
};
You are mixing up $scope and this for your controller model.
Since you are using controllerAs alias....all your data model needs to be bound to this in controller or you need to get rid of alias for controler and only use $scope
Most people would recommend using the alias and this
As was mentioned by #charlietfl in his answer, your example using dataTables is incorrectly assigning the same controller twice, once with ng-controller="colony_Controller" and once with ng-controller="colony_Controller as Main_Module. The data tables inside the second copy of the controller will not have access to the variables in the first controller.
<div ng-controller="colony_Controller">
....
<div ng-controller="colony_Controller as Main_Module">
<table align="center" datatable="" dt-options="Main_Module.dtOptions" dt-columns="Main_Module.dtColumns" class="row-border hover">
</table>
</div>
</div>
To correct this, you need to choose between using the first syntax ($scope) or the second (controller as) and ensure that all the code is using the same format.
In this modified version, dtOptions and dtColumns have been moved to $scope, and the extra controller removed:
$scope.dtOptions = DTOptionsBuilder
.fromSource('data_colony.json')
...
$scope.dtColumns = [
...
];
<div ng-controller="colony_Controller">
...
<div>
<table align="center" datatable="" dt-options="dtOptions" dt-columns="dtColumns" class="row-border hover">
</table>
</div>
</div>
http://plnkr.co/edit/GB0IIQQoEaLN0QPBSjCz?p=preview
i have a table which is having the data retrieved from an api call from my memberController which is displayed inside ng-repeat and its working fine.
I need each Business Name of the member list to link to a separate page(edit_form.html) and display the id value, so that i can pass this along with the api call to get only this particular member detail. So i have added ng-init in my edit form page which calls the function test_funct when the page loads and retrieve each persons id there. unfortunately i am unable to retrieve the id value inside the function.
HTML Template
<div class="page" data-ng-controller="memberController">
<table>
<thead >
<tr>
<th>Business Name</th>
<th>Contact Name</th>
<th>Trade Balance</th>
<th>Cash Balance</th>
<th>Telephone</th>
<th>Account Number </th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="member in details | filter:search">
<td>{{member.businessname}}</td>
<td>{{member.person}}</td>
<td>{{member.balance_trade}}</td>
<td>{{member.balance_cash}}</td>
<td>{{member.telephone}}</td>
<td>{{member.accountnumber}}</td>
</tr>
</tbody>
</table>
</div>
I have the following controller
function memberController($scope, $http, $cookieStore) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
var member_list = "http://www.vb.com/functions/member_list.html?exchangeid=" + exId +
"&contactid=" + conId + "&token=" + token;
$http.get(member_list)
.success(function(response) {
$scope.details = response;
});
$scope.test_funct = function(id) {
$scope.myid = id;
alert($scope.myid); // getting undefined in alert, i expect the id(eg:1123)
}
}
edit_form.html
<div class="page" data-ng-controller="memberController">
<div class="panel-body" ng-init="test_funct()"></div>
</div>
Please assist me on this. Thanks in advance.
There are 2 things going on here.
First, you should separate controllers for the different views, so you end up with something like this:
<div class="page" data-ng-controller="memberController">
<table>
<!-- your whole big table here -->
</table>
</div>
And your editing form as follows:
<div class="page" data-ng-controller="editController">
<div class="panel-body"></div>
</div>
Notice that you now have two distinct controllers - your "editController" and your "memberController".
The second question then becomes, how do you transfer the selected ID from the list view ("memberController") to the edit view ("editController").
There are 2 ways of doing that.
First, you could use a service shared between the controller:
.factory('SelectedId',function() {
return {};
});
And then in your "member" view, you would set it upon clicking:
{{member.businessname}}
Notice the ng-click, which then needs a function in the memberController and the injected service:
.controller('memberController',function($scope,SelectedId) {
$scope.setId = function(id) {
SelectedId.id = id;
};
});
While the editController retrieves it:
.controller('editController',function($scope,SelectedId) {
$scope.id = SelectedId.id;
});
The above option works well, especially for complex things like shopping carts. If all you are doing is passing an ID, I would just stick it in the URL:
{{member.businessname}}
So that the ID is part of the URL. You then can retrieve it in the "editController":
.controller('editController',function($scope,$routeParams) {
$scope.id = $routeParams.member;
});
assuming you are using ng-route, and your route would look like:
$routeProvider.when('/pages/edit_form/:member',{templateUrl:'/route/to/template.html',controller:'editController'});
In html do that
<td>{{member.businessname}}</td>
...
In app.js or where you define route do that
.when('/edit/:memberid',
{
templateUrl:'partials/edit.html',
controller:'editController'
})
In controller you have to take this id by doing that
app.controller("editController",function($routeParams,$scope){
$scope.memberid= $routeParams.memberid;
//Now use this member id to fetch all data
});
Simple html:
<table class="table table-condensed">
<tr data-ng-repeat="customer in customers" data-ng-class="customerSelectedClass(customer)">
<td>
{{customer.Name}}
</td>
</tr>
</table>
In my controller - two functions to select customer and return proper class to highlight a table row:
$scope.customerSelectedClass = function (customer) {
if (customer == $scope.selectedCustomer) {
console.log('returing info for ' + customer.Name);
return "info";
}
return "";
};
$scope.selectCustomer = function (customer) {
console.log('selecting ' + customer.Name);
$scope.selectedCustomer = customer;
}
I noticed that when I click on a customer link, customerSelectedClass function executes twice. selectCustomer function on ng-click directive executes once, as it should. Angular is only included once on the page. I wonder if this is a bug in Angular or something that I am doing wrong?
Behind the scenes, angular is setting up a $watch on the function that is resolving the class name. Because angular uses dirty checking to see if there has been a change, this method will be called twice during the $digest cycle. This is ok.
I would suggest that you don't add this code the the controller though, because if you are managing many css classes, you could be adding a lot of unnecessary code. Try something like this instead:
<table class="table table-condensed">
<tr data-ng-repeat="customer in customers" data-ng-class="{'info': customer == selectedCustomer}">
<td>
{{customer.Name}}
</td>
</tr>
</table>
Then, there is no need for a controller function customerSelectedClass. This will only add the info class if the right-hand side of the : resolves to true. And there is no problem resolving the correct customer in the ng-repeat.
Hope this helps.
I've got a view that needs to be populated conditionally.
Scenario:
A manager will select a users name on screen B, then will be navigated to the same form the user filled in EG. screen A, except that the said manager will have the option to approve or deny the request of the user.
I've seen that in my VM on screen A I can do the following.
var vm = {
activate: function (data) {
console.log(data);
var id = data.id || -1;
if (id !== -1) {
router.isNavigating(true);
http.json('/api/user/'+ id )
.done(function (response) {
ko.viewmodel.updateFromModel(vm.userInfo, response);
router.isNavigating(false);
});
}
}
};
And then B (view & view model)
view
<table>
<thead>
<tr>
<td>User</td>
<td>Date Requested</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<tr>
<td>Mike</td>
<td>19 Jun 2013
</td>
<td>
<input type="button" value="Go" data-bind="click: function() { buttons.goTo(6) }" />
</td>
</tr>
</tbody>
</table>
viewmodel
define(['durandal/plugins/router'], function (router) {
var buttons = {
goTo: function (id) {
console.log('goTo clicked');
//this does work in conjunction with my code on B
router.navigateTo('#/userinfo?id=' + id);
}
};
var vm = {
buttons: buttons
};
return vm;
});
My issue is that I'm not sure what the best way/or how to for that matter to get Durandal to navigate to page A from B... Is what I'm doing right? As it feels a little bit "hacky"
The navigation, at least to me, is designed to mimic standard MVC web navigation. In this case, since you already know that you want to go to 6, why not use an anchor like so
<a href="#/userinfo?id=6"/>
A better way would be to register your route with an id splat like so your route would become
routes.map({route: 'userinfo/:id, ...
<a href="#/userinfo/6" />
This way you can access the splat on the activate method..there are several examples out there but I don't have links to them. Basically the activate method of your userinfo viewmodel will accept a parameter and from there you can load an entity or whatever you like. Hope this helps.
Brad