I called ng-click like this:
<div ng-repeat="(key,value) in filterdata">
<div ng-click="filter(key,value)">
{{key}} ::::::: {{value}}
</div>
</div>
and my Controller function looks like this:
$scope.filter = function(key,value){
$location.search(key, value);
var filter = $location.url();
service.get(filter).success(function(data) {
$scope.applicationdata = data.data;
console.log($scope.applicationdata);
});
}
and my HTML file has ng-repeat like this:
<div class="resultsa" ng-repeat="data in applicationdata">
{{data.name}}<hr>
<div ng-repeat="metadata in data.metadata">
{{metadata.name}} , {{metadata.pivot.value}}
<hr>
</div>
</div>
The first time I click, my service function is called and my model is updated but my view doesn't update. When I click a second time, my view properly updates. Can anyone tell me why this happening?
This is because you are changing the value of the model after the digest cicle was triggered, and in a different context. For solving this you need to call $scope.$apply() after setting the application data, for triggering another digest cycle.
Related
I am facing some issue. I have some nested controller within one parent controller and I need it to execute as per some condition using Angular.js. I am explaining my code below.
NABH.html:
<div ng-controller=NABHParentController>
<div ng-show="showNabh">
<div ng-include="'nabh1.html'"></div>
</div>
<div ng-show="showNabh1">
<div ng-include="'nabh2.html'"></div>
</div>
</div>
nabh1.html:
<div class="right_panel" style="display:block;" id="auditnabh" ng-controller="NABHController">
<td class="sticky-cell" ng-click="initiateNABH(nabh.NABHAuditID)">
</td>
</div>
nabh2.html:
<div class="right_panel" ng-controller="NABH2Controller">
<h2 class="page-title">NABH (INT012017001)</h2>
<div>
NABHParentController.js:
var app=angular.module('demo');
app.controller('NABHParentController',function($scope,$http,$state,$window,$location,$filter){
$scope.showNabh=true;
$scope.showNabh1=false;
})
NABHController.js:
var app=angular.module('demo');
app.controller('NABHController',function($scope,$http,$state,$window,$location,$filter,getBothIdToAuditDetailPage)
{
$scope.initiateNABH = function(aid) {
$scope.$parent.$parent.showNabh=false;
$scope.$parent.$parent.showNabh1=true;
}
})
Here Initially all controller are loading and nabh1.html is displaying first. When user will click on that td click event the second part html is showing. Here I need when user will click on that ng-click="initiateNABH(nabh.NABHAuditID)" the second view will open and the resepective controller will start execute. Initially only displaying view related controller will execute. Please help.
It sounds like using ng-if instead of ng-show will solve your problem:
<div ng-if="showNabh">
<div ng-include="'nabh1.html'"></div>
</div>
<div ng-if="showNabh1">
<div ng-include="'nabh2.html'"></div>
</div>
The difference is that while ng-show will "only" hide the element using css when the expression is falsy, ng-if will not create the element if it's falsy and as a result will not initiate the controller until ng-if is truthy.
Also, I would probably move the initiateNABH function to the parent controller - it will still be available in the child controller but makes the code less likely to break since you don't have to use $parent:
var app=angular.module('demo');
app.controller('NABHParentController',function($scope,$http,$state,$window,$location,$filter){
$scope.showNabh=true;
$scope.showNabh1=false;
$scope.initiateNABH = function(aid) {
$scope.showNabh=false;
$scope.showNabh1=true;
}
})
So I have a link in an html box and when clicking the link iam trying to have it show a whole new set of divs replacing the present divs.
I tried :
<a href="" ng-click="Search('Show Products A B C')" > Show Products </a>
Search calls in the function in the controller which returns the data for the A B C products, which are then displayed using
<div ng-repeat="products in Search( 'Show Products A B C')" </div>
I am basically trying to do something like this:
<div ng-repeat=" href="" ng-click="Search('Show Products A B C')"> </div>
which is not proper syntax I understand.
But right now nothing happens.
Basically from that ng-click i would like to call that portion of the code (ng-repeat) because right now they are not connected.
thanks
ng-repeat will respond to changes in its argument, but your argument is a function Search(). I would suggest the following:
In your search function:
$scope.Search = function(arg) {
// do your search logic
$scope.productList = <search result list>
}
then in html
<div ng-repeat="products in productList" </div>
What you should do is to have some array or object A bound to $scope, then when you call search you update A and the changes will be reflected on your view
$scope.show=true;
$scope.products =[A,B,C];
$scope.Search = function() {
// do list update
$scope.show=false;
$scope.products =[D,E,F] ;
}
You also need to change ng-repeat to this:
<div ng-repeat="product in products" </div>
And add ng-show to the first link:
Click Me
Edit:
Check this fiddle for a working example.
Edit:
Fiddle updated reflecting latest changes.
In my app, i am calculating total bill and displaying on my view. First time its work fine. But when I increment the $scope.bill_total it is not updating the view. But in console it is changing. I have tried $scope.$apply(). But it is throwing error.what are the reasons of view not get updating in general case Can anyone explain it?
HTML
<div id="total" class="col col-30 cart-item text-right text-black">
Bill Total<br/> ${{ bill_total }}
</div>
<button class="button button-small button-light" ng-click="increment()"> +</button>
JavaScript:
$scope.calculate = function () {
$scope.bill_total = parseFloat($scope.gross_bill) + parseFloat($scope.taxes) + parseFloat($scope.tips);
}
$scope.calculate();
$scope.increment = function () {
$scope.gross_bill++;
$scope.calculate();
console.log($scope.bill_total )
}
Need to see more of your code, but why are you updating gross_bill when you are expecting bill_total to change?
If you aren't using gross_bill in your template, it won't be watched and hence changing it's value won't redraw the view.
So, modify things that are bound in your template. If there's some reason I'm wrong and you need to do scope.apply, and maybe that's the case, try wrapping your code in a $timeout which will trigger a digest, is the 'recommended' solution preferred to calling apply directly.
notes on apply vs timeout
as we can only see part of your source code, it looks all good.
to test if everyting is in the same digest scope, you can manually do an async apply:
$scope.increment = function () {
setTimeout(function () {
$scope.gross_bill++;
$scope.calculate();
$scope.$apply();
console.log($scope.bill_total );
});
}
and pls also double check below points:
if bill_total is one-time binding {{ ::bill_total }}
if the directive scope is isolated with one-way binding bill_total
The problem is probably that $scope.bill_total is not an object and therefore cannot be watched. You need to change it to something like $scope.bill_total = {value: 3}. Then when you update the value it should be updated correctly in your view. There should be no reason to call $scope.apply since you are within a digest cycle already.
Make sure to change your html to :
<div id="total" class="col col-30 cart-item text-right text-black">
Bill Total<br/> ${{ bill_total.value }}
</div>
I'm trying to use ng-include with ng-init to re-use the same component by only changing its data.
The component code ("slider.html", which has no controller) looks like this:
<div ng-repeat="person in persons">
{{person.name}}
</div>
From the main view, I want to reuse the same component changing "persons" list so in the view I have:
<!--slider #1 -->
<div ng-init="persons=english" ng-include ="'inc/app/views/widgets/slider.html'"></div>
<!-- slider #2 -->
<div ng-init="persons=german" ng-include ="'inc/app/views/widgets/slider.html'"></div>
and in the controller I initialize the 2 lists "english" and "german" like this:
$scope.english = records.filter(function(t){return t.nationality=="english";});
$scope.german = records.filter(function(t){return t.nationality=="german";});
What happens is that the 2 components shows the same list of data (german); is there a way to bind the 2 different sets to the components?
That (having both lists being set as German) happens because, at the end, you are only using one controller, which has only one scope in which the persons varaiable exists. When AngularJS starts its bootstrapping process, it processes the first ng-init, updating the current controller's persons variable to English. Then it processes the second ng-init, updating again the same persons variable now to German. Then, when the ng-repeat is rendered, it will take the current and unique persons variable data, hence, being everything in German.
What you can do is to have an independent controller per component (slider.html), so each controller will have its own binding variables so you can create a persons variable for each one and initialize every controller's variable independently with your ng-init directive. Example:
<div ng-controller="MySubController" ng-repeat="person in persons">
{{person.name}}
</div>
...
<!--slider #1 -->
<div ng-init="initMySubController(english)" ng-include ="'inc/app/views/widgets/slider.html'"></div>
<!-- slider #2 -->
<div ng-init="initMySubController(german)" ng-include ="'inc/app/views/widgets/slider.html'"></div>
In a JS file:
var myApp = angular.module('myApp',[]);
myApp.controller('MySubController', ['$scope', function($scope) {
$scope.persons = [];
$scope.initMySubController = function(personsData) {
$scope.persons = personsData;
}
}]);
i would like to have a list with entries of objects. If i click on an entry in that list i want to see the details of the object and an edit button on an area at the right side of the list. If i click that button the details disappers and a form to edit the object should appear.
html
<table class="table table-striped">
<tr
ng-repeat="object in objects"
ng-click="select(object.id)"
>
<td>{{object.name}}</td>
</tr>
</table>
<button ng-click="edit(selectedObject.id)">Edit</button>
<div class="view">
Name: {{selectedObject.name}}
</div>
<form>
<label>Name</label>
<input ng-model="object.name">
</form>
controller.js
myModule.controller('MyController', function($scope, MyService) {
$scope.objects = MyService.getObjects();
$scope.select = function(id) {
$scope.selectedObject = angular.copy(MyService.getObject(id));
};
$scope.edit = function(id) {
...
};
});
In the edit function i could use the selectedObject, but maybe in future i also want to edit the object directly without selecting it before. So first i could do the same like in the select function but then i would call the service twice to receive the same object...
Also i don't know really how to handle the toggle between view- and editmode.
Thanks in advance!
You should give the detail view and the edit form their own Controller, that way they're ready to be seperated.
Also a strong recommendation is using https://github.com/angular-ui/ui-router Nested-Views and Multiple/Named Views to manage your controllers.
You can then make the list view the parent and add the other 2 as child views with their own url like /item/:id/view and /item/:id/edit, see $stateParams for getting the values from the URL.
I am not 100% sure about your question but you could show/hide the input
$scope.edit = function () {
$scope.editmode = true
};
and
<div class="view" ng-show="!editMode">
Name: {{selectedObject.name}}
</div>
with
ng-show="editmode"
on the input
or you could use
ng-readonly="!editmode" on the input (then you won't need another div to display the name)
If your planning to display obejcts has a table, please consider ngGrid which allows editing inside the grid itself