So here's my workflow-
I've got an HTML file in which a div tag is created on which I've placed ng-repeat which iterates and gives me a list of items. On this div tag, I've placed an ng-click function. On clicking and item in the div tag, a modal-popup is opened.
What I need is to pass the id of the item from ng-repeat and show the data of this id in the modal-popup.
Now I've written the code upto here and all things are working fine, but the issue that I'm facing is if I click on any of the items from ng-repeat the first item is only returned, and hence data for the id of the first item is only being displayed in the modal-popup.
How could I get the id of the particular item clicked (and not the first item) and pass it to the controller?
Here's my working code -
main HTML:
<div id="main">
<div ng-repeat="data in JsonData" ng-click="openModal()">
<div id="widget">
<div id="{{$index}}">
<div>
<h2 class="font-bold no-margins" id="{{data.itemName}}">
{{data.itemName}}
</h2>
</div>
<div>
// other code
</div>
</div>
</div>
</div>
</div>
main controller.js:
$scope.openModal = function () {
$rootScope.elementid = document.getElementById('main').getElementsByTagName('div')[2];
$rootScope.variableId = $scope.elementid.id; // This gives the value in {{$index}}
$rootScope.elementname = document.getElementById('main').getElementsByTagName('h2')[0];
$rootScope.variablename = $scope.elementname.id; // This gives the value in {{data.itemName}}
$uibModal.open({
templateUrl: 'url/to/modal/popup.html',
controller: 'PopUpController',
scope : $scope,
windowClass: "animated fadeIn",
backdrop:'static'
});
};
On doing inspect element, I found that the elements are getting their correct id.
This is for the {{itenName}} code: (names are coming correct)
h2#CorrectName.ng-binding
and this is for the {{$index}} code: (here, id is incrementing for the items of ng-repeat)
div#0.ng-binding
So where am I wrong here? Is it due to any asynchronous call? Or is it due to ng-binding (i.e id of the item is returned before the ng-binding function completes)?
I'm really stuck here for a couple of days now. Any help would be much appreciated. Thanks.
You should not get the HTML data, instead you should pass the values to your function
ng-click="openModal(data)"
and from that on you can get the data in your funtion
$scope.openModal = function (data) {
and now you can do with that data whatever you want
console.log(data.itemName)
angular.module('test', []).controller('test', function($scope) {
// Test data
$scope.JsonData = [{itemName: "Test"}, {itemName: "OtherTest"}];
$scope.openModal = function(data) {
// handling data
console.log(data);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="test">
<div ng-repeat="data in JsonData" ng-click="openModal(data)">
<div id="widget">
<div id="{{$index}}">
<div>
<h2 class="font-bold no-margins" id="{{data.itemName}}">
{{data.itemName}}
</h2>
</div>
</div>
</div>
</div>
</div>
you can pass your $index to ng-click="openModal()" , so it will be ng-click="openModal($index)" .
controller
$scope.openModal = function (id) {
console.log(id); // log the clicked id
}
you can pass selected JsonData object as parametr of openModal function
<div ng-repeat="data in JsonData" ng-click="openModal(data)">
also you can pass selected obj to modal controller
$scope.openModal = function (selectedObj) {
$uibModal.open({
templateUrl: 'url/to/modal/popup.html',
controller: 'PopUpController',
scope : $scope,
windowClass: "animated fadeIn",
backdrop:'static',
resolve : {
selected: function () {
return selectedObj;
}
}
});
};
and get selected obj in PopUpController
app.contoller('PopUpController',['selected', function(selected){
console.log(selected)
}])
Related
I'm trying to implement an Angular version of an autocomplete textbox. I found some working examples, but none seem to exhibit the behavior I'm getting.
The autocomplete functionality itself works fine. When a suggested item is selected, the control correctly handles the selection. Subsequent uses of the control (typing in the autocomplete box, making a selection) fail to engage the 'selected' event/condition, although the autocomplete bit continues to work.
Here's my module & controller:
var app = angular.module('myapp', ['angucomplete-alt']); //add angucomplete-alt dependency in app
app.controller('AutoCompleteController', ['$scope', '$http', function ($scope, $http) {
//reset users
$scope.Users = [];
$scope.SelectedUser = null;
//get data from the database
$http({
method: 'GET',
url: '/UserRoleAdministration/Autocomplete'
}).then(function (data) {
$scope.Users = data.data;
}, function () {
alert('Error');
})
//to fire when selection made
$scope.SelectedUser = function (selected) {
if (selected) {
$scope.SelectedUser = selected.originalObject;
}
}
}]);
I'm guessing the problem is in there, but I don't know what it is. I include the bit from my view below, although there doesn't seem to be much there to fuss with:
<div class="form-group">
<div ng-app="myapp" ng-controller="AutoCompleteController">
<div angucomplete-alt id="txtAutocomplete" pause="0" selected-object="SelectedUser" local-data="Users" search-fields="RegularName" placeholder="People Search" title-field="RegularName" minlength="2" input-class="form-control" match-class="highlight"></div>
<!--display selected user-->
<br /><br />
<div class="panel panel-default" id="panelResults">
<div class="panel-heading"><h3 class="panel-title">Manage Roles for {{SelectedUser.RegularName}}</h3></div>
<div class="panel-body">
<div class="row">
<div class="col-md-2">
<img src="~/Images/avatar_blank.png" width="100%" />
</div>
<div class="col-md-4">
<div class="row">
<div class="col-md-4">Selected User:</div> <div class="col-md-6">{{SelectedUser.RegularName}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
Any help would be appreciated!
UPDATE
After fixing the mistake Yaser pointed out, I wasn't getting any information regarding the selected object. So I set the page to output the entire object, rather than the specified fields, and I noticed I was getting information about the selected object, and on subsequent attempts as well.
So this worked: {{SelectedUser}}
This did not: {{SelectedUser.Department}}
Then I looked at the object and noticed its format. It had "title" and "description", and description had inside it the key/value pairs.
So now this works: {{SelectedUser.description.Department}}
And that's it.
Because the first time you are setting $scope.SelectedUser as a function but inside that you are rewriting the same one with an object. so next time it is not a function any more, try to rename the function:
$scope.setUser = function (selected) {
if (selected) {
$scope.SelectedUser = selected.originalObject;
}
}
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 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 have generated a list with ng-repeat, where each item has a count variable. In each list item I have a link.
I want to increment the count when I click the link.
I tried the following way but it not work.
My Controller :-
myApp.controller('allpost', function ($scope, $http, $stateParams, Allposts) {
var id = $stateParams.id;
Allposts.GetAllposts(id).then(
function (response) {
$scope.allPosts = response.data.posts;
});
function ctrl($scope) {
$scope.increment = function(item){
item.count += 1;
}
}
})
and view like :-
<ion-content class="padding" lazy-scroll>
<div class="row no-padding HomeRowsList">
<div class="item itemfull" ng-repeat="post in allPosts">
<div class="item item-body">
<div>
<div class="title-news">
<div class="title" ng-bind-html="post.content"></div>
<div class="countbg">عدد المرات : {{post.custom_fields.azkarno}}</div>
<span>{{post.count}}</span><a onclick="ctrl(post);">Increment</a>
</div>
</div>
</div>
</div>
</div>
</ion-content>
In controller use
$scope.increment = function(item){
item.count += 1;
};
instead of
function ctrl($scope) {
$scope.increment = function(item){
item.count += 1;
}
}
and in html use
<span>{{post.count}}</span><a data-ng-click="increment(post)">Increment</a>
instead of
<span>{{post.count}}</span><a onclick="ctrl(post);">Increment</a>
It should be ng-click instead of onclick & the method name should be increment instead of ctrl.
Also remove unnecessary ctrl function wrapper from the increment method which is not needed at all, because whatever you wanted to call from the html should be included in the $scope of controller.
Markup
<span>{{post.count}}</span><a ng-click="increment(post);">Increment</a>
It's an ad (discount codes for e-shops) app I'm trying to make.
Ads are listed in to Array , each ad having 4 things (name, image link , discount (%) , discount code)
This is how I list the ads (ng-repeat is used) :
<div class="list">
<div class="item item-thumbnail-left" href="#" ng-repeat="item in dovanosListArray" >
<img ng-src={{item.image}}>
<h2>{{item.name}}</h2>
<button menu-toggle="right"class="button-icon icon ion-ios7-arrow-forward" ng-click="modal.show()"></button>
<p>Nuolaida : {{item.discount}} %</p>
</div>
</div>
So when you click the one you want, modal opens. In the modal , I need to show the same {{item.name}} again and give it's {{item.discountcode}}. How am i supposed to do this ? I can't use ng-repeat because there are other items in the same array as well.
Sorry for my English, I think that you need is something like this:
var modalInstance = $modal.open({
templateUrl: 'Modal.html',
controller: 'ModalCtrl',
resolve: {
item: function () {
return item;
}
}
And in you controller:
angular.controller('ModalCtrl', ['$scope','item',
function($scope, item , ) {
$scope.item=tem;
..........................
}])
So in your controller you already hace the value of item;
Pass the item as an object parameter in your modal.show() function.