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.
Related
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
}
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.
I`m new to angularJS. I have a table, I make a request and output some default data in my tablerows from Controller2. Now I want to make a different request and output other data in the same table,but this time from Controller1. How can I do this ?
Html
<tr ng-repeat="stats in statsFromTable" ng-show="statsFromTable.length > 0">
<td><span ng-bind="stats.PERS"></span></td>
JavaScript
Controller2 -- > $scope.statsFromTable = data.REQUEST_ATTRIBUTES.historyList; // the first default request
Controller1 -- > ???
Don't use $rootScope to share info between controllers. For that purpouse you can use a service.
So your code could look like:
angular.
module('yourAngularModule', []).
controller('MyController', ['$scope','myService', function ($scope, myService) {
$scope.number1 = myService.number;
}]).
controller('MyController2', ['$scope','myService', function ($scope, myService) {
$scope.number2 = myService.number;
}]).
service('myService', [function() {
var service = {
number:0
};
return service;
}]);
})(window.angular);
And then you could bind the data like:
<div ng-controller="MyController">
<h3>Controller 1</h3>
{{number1}} // Will display service.number --> 0
</div>
<div ng-controller="MyController2">
<h3> Controller 2</h3>
{{number2}} // Will display service.number --> 0
</div>
I did a plnkr where you can take a look at how two different controllers share info via service.
you can use $rootScope to do this. here is the example demo for you i have created
I have two types of controllers:
The first type of controller only appears once on an html page ("SingleChildController").
The second type of controller appears twice on the same page ("MultipleChildController") and is differentiated by the value of its property "instance".
Both of these are nested within my ParentController (see code below).
How can I access data from any of my 3 child controller instances in the ParentController?
I have tried adding two services, one for the SingleChildController and one for the MultipleChildController, but it seems like by doing so I am duplicating a lot of code. This is especially true in my actual code where each controller has many properties to monitor. Is there a better way to accomplish this?
EDIT: For further clarification, this view is for a form and I want to get all of my data back up into the ParentController so that I can submit my form.
(function() {
var app = angular.module('myApp', []);
app.controller('ParentController', ['$scope',
function($scope) {
var parent = this;
parent.singleName = "";
parent.multiple1Name = "";
parent.multiple2Name = "";
}
]);
app.controller('SingleChildController', ['$scope',
function($scope) {
var single = this;
single.name = "";
}
]);
app.controller('MultipleChildController', ['$scope',
function($scope) {
var multiple = this;
multiple.instance = "";
multiple.name = "";
}
]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ParentController as parent">
<!-- I would like these to show the data that was inputted below -->
ParentSingleName: {{parent.singleName}} <br />
ParentMultiple1Name: {{parent.multiple1Name}} <br />
ParentMultiple2Name: {{parent.multiple2Name}} <br /><br />
<div ng-controller="SingleChildController as single">
<input type="text" ng-model="single.name" />: {{single.name}}
</div>
<div ng-controller="MultipleChildController as multiple1" ng-init="multiple1.instance='first'">
<input type="text" ng-model="multiple1.name" />: {{multiple1.instance}} - {{multiple1.name}}
</div>
<div ng-controller="MultipleChildController as multiple2" ng-init="multiple2.instance='second'">
<input type="text" ng-model="multiple2.name" />: {{multiple2.instance}} - {{multiple2.name}}
</div>
</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.