I have two controllers, one nested inside the other, both using ng-repeat to essentially list arrays of related data. I'd like to access one of the properties in the ng-repeat of the parent controller in the child controller. I'm pretty new to Angular and not sure how to get this working or if I'm approaching it the wrong way. Any guidance would be helpful.
HTML
<div class="container" ng-app="myApp">
<div class="task" ng-controller="TaskController as taskCtl" ng-repeat="task in tasks">
{{task.name}}
<ul>
<li ng-controller="AttachmentController as attachmentCtl" ng-repeat="attachment in attachments">{{attachment.name}}</li>
</ul>
</div>
</div>
JS
var app = angular.module('myApp', []);
app.controller('TaskController', ['$scope', function ($scope) {
$scope.tasks = [{name:'thing1', id: '123456'}, ... ];
}]);
app.controller('AttachmentController', ['$scope', '$http', function ($scope, $http) {
$scope.attachments = [];
$scope.init = function init() {
$http.get('/api/attachments&task_id=' + **HOW_DO_I_GET_TASK_ID_HERE** )
.then(function(response) {
$scope.attachments = response.data;
});
};
$scope.init();
}]);
I'd like to load the attachments as they relate to the tasks based on the task id for a given iteration through ng-repeat. Not sure if I'm going about this the wrong way.
Thanks
Although it would be better to use a ng-repeat with a filter on all the attachments with the given id. Since now you are calling the /api/attachments&task_id for each task iteration.
Or to send the list of attachments directly on the /api/tasks call. Therefor you could loop them instantly when looping the tasks, without the need of fetching them on each iteration.
A possible solution according to your code provided:
<div class="container" ng-app="myApp">
<div class="task" ng-controller="TaskController as taskCtl" ng-repeat="task in tasks">
{{task.name}}
<ul>
<li ng-controller="AttachmentController as attachmentCtl" ng-repeat="attachment in getAttachments(task.id)">{{attachment.name}}</li>
</ul>
</div>
</div>
app.controller('AttachmentController', ['$scope', '$http', function ($scope, $http) {
$scope.getAttachments = function(id) {
$http.get('/api/attachments&task_id=' + id)
.then(function(response) {
return response.data;
});
};
}]);
Something like this from the child controller should work:
HTML:
<div class="container" ng-app="myApp">
<div class="task" ng-controller="TaskController" ng-repeat="task in tasks">
{{task.name}}
<ul>
<li ng-controller="AttachmentController" ng-repeat="attachment in fetchAttachments(task)">{{attachment.name}}</li>
</ul>
</div>
</div>
JS
Child Controller:
This fetchAttachments will be called for every iteration of the parent ngRepeat. You will have to "return" the result of the Ajax call to this function for it to work.
$scope.fetchAttachments = function (task) {
// call ajax
// return the result of ajax
}
Related
I have a very hierarchical data structure in JSON. I also have a re-usable (Django) template that gets bound to part of that structure. So, I need to know where in that structure I am for any given template. I am almost there:
http://jsfiddle.net/trubliphone/fd64rn3y/
The missing bit is being able to pass the current ng-model to a controller.
Here is some code (but the jsfiddle above shows more detail):
my_app.js:
var myApp = angular.module('myApp', []);
myApp.factory('$global_services', ['$http', function($http) {
var data = {};
$http.get("some_url", {format: "json"}) {
/* THIS REQUEST RETURNS A BIG CHUNK OF HIERARCHICAL JSON */
.success(function (data) {
data = data;
})
});
return {
getPathFromModel: a_clever_fn_i_wrote_that_returns_a_string(),
getModelFromPath: a_clever_fn_i_wrote_that_returns_a_model()
}
}]);
myApp.controller('MyController', ['$scope', '$attrs', '$global_services', function( $scope, $attrs, $global_services ) {
if ($attrs.currentModelPath) {
/* if you passed current_model_path, get the current_model too */
$scope.current_model_path = $attrs.currentModelPath;
$scope.current_model = $global_services.getModelFromPath($scope.current_model_path);
}
else if ($attrs.currentModel) {
/* if you passed current_model, get the current_model_path too */
$scope.current_model = $attrs.currentModel;
$scope.current_model_path = $global_services.getPathFromModel($scope.current_model);
}
}]);
my_template.html:
<div ng-app="myApp">
<div ng-controller="MyController" current_model_path="data">
{{current_model.name}}:
<ul ng-repeat="child in current_model.children">
<input type="text" ng-model="child.name"/> {{ child.name }}
<!-- LOOK: HERE IS A NESTED CONTROLLER -->
<div ng-controller="MyController" current_model="child">
{{current_model.name}}:
<ul ng-repeat="child in current_model.children">
<input type="text" ng-model="child.name"/> {{ child.name }}
</ul>
</div>
</ul>
</div>
</div>
The problem is in the "div" element for the nested controller; I pass the {{child}} ng variable as an attribute, but when the controller recieves it, it just interprets it as the JavaScript string "child". How can I pass the actual model object?
Thanks.
<div ng-controller="MyController" ng-init="data = child">
this will add an object to the inner scope named data.
I'm having difficulties in solving this. What I'm trying to achieve is to update iterated objects which is passed in to a function in a different controller.
Here is my controllers -
angular.module('eatmapp.controllers', ['eatmapp.services'])
.controller('AppCtrl', function($scope) {
$scope.intoCart = function(item) {
if(item.type == 'variations'){
item = newItemObj;
}
}
})
.controller('BrowseCtrl', function($scope, dataService, $localstorage) {
dataService.getItems().then(function(returnData) {
$scope.items = returnData.products;
})
});
Here is my view -
<div ng-controller="BrowseCtrl">
<div class="list card product" ng-repeat="item in items" ng-click="intoCart(item)">
<div class="item item-text-wrap">
<span class="ifs-productcat" ng-repeat="category in item.categories">{{category}}<span ng-if="$index != item.categories.length - 1">,</span></span><br>
<h3>{{item.title}}</h3>
<h3>Rs.{{item.price}}</h3>
</div>
</div>
</div>
I need to update item object with newItemObject in iteration(ng-repeat) implemeted in template view after doing some condition check with method (intoCart) in another controller(AppCtrl). I'm fairly new to javascript programming and I'm looking for some help.
The problem I had was not able to get access to 'ng-repeat' child scope in controller.
I solved this using 'this.item' in controller rather than passing the whole object or index.
HTML -
<div class="list card product" ng-repeat="item in items" ng-click="intoCart()"></div>
Controller -
angular.module('eatmapp.controllers', ['eatmapp.services'])
.controller('AppCtrl', function($scope) {
$scope.intoCart = function() {
item = this.item; // current (ng-click) child scope of ng-repeat
if(item.type == 'variations'){
item = newItemObj;
}
}
})
Now, whenever I made changes to 'item' object, it automatically updates scope in view (ng-repeat).
Once way I like to handle this is by using services as setters and getters. The problem is you have to include the service with every controller that needs to access it, but if you don't have too many it's no big deal. So something like this:
.service('userFirstName', function() {
var userFirstNameProp;
return {
getter: function() {
return userFirstNameProp;
},
setter: function(value) {
userFirstNameProp = value;
}
};
})
Then you can call userFirstName.getter() or userFirstName.setter("John") as appropriate.
Im having problem communicating child controller with parent controller,
i hv a function that push data to parent array which is included in ngrepeat.
after pushing the parent array is appended correctly, and its length is shown correctly in parent controller, yet the ngrepeat doesnot refresh.
<div ng-controller="parentCtrl">
This works {{shared.arr.length}} <br/>
This works Too{{shared.arr|json}} <br/>
<div ng-repeat="a in shared.arr">
{{a}} This dont, it only show old data.
</div>
<section ng-contoller="childCtrl">
<button ng-click="test()">Test</button>
</section>
</div>
angular.module('testApp')
.controller('parentCtrl', function ($scope) {
$scope.shared = {arr:[1,2]};
});
.controller('childCtrl', function ($scope) {
$scope.test = function(){$scope.shared.arr.push(4);}
});
angular.module('testApp', [])
.controller('parentCtrl', ['$scope', parentCtrl])
.controller('childCtrl', ['$scope', childCtrl]);
function parentCtrl ($scope) {
$scope.shared = {
arr: [1, 2]
};
}
function childCtrl ($scope) {
$scope.test = function (arr) {
arr.push(4);
}
}
<div ng-controller="childCtrl">
<button ng-click="test(shared.arr)">Test</button>
</div>
http://jsfiddle.net/kikill/zhzb3pxh/
try this code.
there were 2 mistakes:
1) ng-controller="childCtrl", not ng-contoller="childCtrl"
2) you passed into 'test' function parent's variable. It can make a lot of errors that no so clear in this example, but it can be.
Use 'controller as' syntax. You can read about this here.
Since this code is working fine in my case, I will assume that in your code also you have done the mistake of writing controller as contoller in<ng-contoller="childCtrl"> , which is a very silly mistake :)
I have a controller that contains data to be iterated over with an ng-repeat, and I'm using it alongside this selection model directive.
After using ng-repeat to create several entries in the DOM, the bindings to $scope.selectedItems stop working.
I know ng-repeat create a new child scope for each iteration, but shouldn't the updates to the selectedItems property still be picked up by binding to values in the MyController?
Controller:
(function() {
angular.module('myModule', ['product.module'])
.controller('MyController' ['$scope', 'SomeService' function($scope, ProductService) {
$scope.selectedItems = [];
$scope.productService = new ProductService() //constructor pattern object
$scope.products = $scope.productService.items;
$scope.productService.fetchData(); //grabs data from server and sets the productService.items to an array of objects
}]);
})();
HTML
<div ng-controller="MyController">
<ul>
<li ng-repeat="product in products"
selection-model-type="checkbox"
selection-model-mode="multiple"
selection-model-selected-items="selectedItems">
{{product.name}}
</li>
</ul>
<div ng-controller="MyController"> <!-- this binding doesn't work after the ng-repeat takes place -->
There are {{selectedItems.length}} products
</div>
productService.items may refer to the same instance all the time but selectedItems surely not. Use only one controller or place selectedItems into a service.
<div ng-controller="MyController">
<ul>
<li ng-repeat="product in products"
selection-model-type="checkbox"
selection-model-mode="multiple"
selection-model-selected-items="selectedItems">
{{product.name}}
</li>
</ul>
There are {{selectedItems.length}} products
</div>
I have a controller that receive from server the JSON below:
"[{\"nome\": \"Ricardo Andrade\"}]"
My controller is removing the \ by parsing the JSON, my controller is:
app.controller("userLogado", function ($scope, $http) {
//$http.get('web/core/components/home/nav.json').
$http.get('http://localhost:2099/api/autenticacao/NomeUsuarioLogado').
success(function (data) {
debugger;
var result = json_parse(data);
var sNome = '';
$.each(result, function(key, item) {
sNome = item.nome;
});
})
});
My question is, how can I take the result of this controller and show in my HTML using AngularJS?
I tried to use an Alert and got the right name like this: "Ricardo Andrade".
Thanks in advance!
Its as simple as putting attaching the result to the controller.
Once you get the result you want, just attach it to scope.
app.controller("myCtrl", function ($scope, $http) {
$scope.result = "Ricardo Andrade"
});
And the HTML
<div ng-controller="myCtrl">
{{result}}
</div>
If you have more than one name, you will need to ng-repeat the names.
<div ng-controller="myCtrl">
<ul ng-repeat='name in result'>
<li>{{name}}</li>
</ul>
</div>
<ul>
<li ng-repeat="names in result">
[{{$index + 1}}] {{names.nome}}
</li>
</ul>
Have a look at ngRepeat:
Docs: https://docs.angularjs.org/api/ng/directive/ngRepeat
W3Schools: http://www.w3schools.com/angular/angular_directives.asp
EDIT:
I hear it's better to use ng-repeat with arrays, so you might want to do that if you feel like it:
Your controller:
$scope.allNames =[];
app.controller("userLogado", function ($scope, $http) {
//$http.get('web/core/components/home/nav.json').
$http.get('http://localhost:2099/api/autenticacao/NomeUsuarioLogado').
success(function (data) {
debugger;
var result = json_parse(data);
for(var name in result) {
$scope.allNames.push(angular.copy(result[name]));
}
})
});
Your HTML:
<ul>
<li ng-repeat="names in allNames">
[{{$index + 1}}] {{names.nome}}
</li>
</ul>
The ul list must be inside a container with ng-controller attribute.
E.g.
<div ng-controller="userLogado">
<ul list here>
</div>
The benefit of using an array with ng-repeat is that you can filter (Read here) and order (Read here) your data.