How to load controller as per specific condition using Angular.js - javascript

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;
}
})

Related

How inject data after every certain count in angularjs

I have some SQL data which I am fetching from the database, I am using angular js with an ng-repeat directive to list all rows below is my code:
<div class="wrapper">
<div class="content" ng-repeat="row in rows">
{{row.someData}}
</div>
</div>
Now I have some custom advertisement banners which I want to show after every 4th row but I don't know how to it with angular Js so please help me here
Apart from Panos K's way what you can do is have one flag to check if banner data is received from web service and then add it after every 4th row of data already loaded. So, for that have ng-if condition inside ng-repeat & then bind that new bannerData arry/objects with index as $index/4.
Check below Plunker example I've created to demonstrate this. Click on Banner data button to make async call to get banner data & then binding it to existing data loaded using ng-repeat
<div ng-repeat="x in records track by $index">
<div class="column">{{x.name}}</div>
<div class="column">{{x.abbreviation}}</div>
<div ng-if="isBannerDataAvailable && ($index+1) % 4 === 0" class="banner">
<p>Banner After every 4th row</p>
<p> {{showBannerData($index)}} </p>
</div>
</div>
Where showBannerData() can be:
$scope.showBannerData = function($index) {
var index = $scope.Math.round(($index + 1) / 4) - 1;
return $scope.bannerData[index].Banner;
}
Working plunker Example
First edit your question with your last comment.
what you need to do is add banners to your model ($scope.rows in your case)
So when you fetch your banners (onSuccess) do this
banners.forEach((element,index)=>{
if(index%4==0)
$scope.rows.splice(index,0,element);
})

AngularJS: ng-if outside ng-repeat breaks ng-repeat

AngularJS Verion: 1.3.8
JSFiddle: http://jsfiddle.net/uYFE9/4/
I've been working on a small AngularJS application, and ran into a bit of a problem. I have an ng-repeat on a page, which fills in the contents of a form. The amount of items in the form is defined by a dropdown bound to a model, and populated using ng-options. Something like:
<select id="testAmount" ng-model="selectedItem" ng-options="item.name for item in items"></select>
<form role="form" name="testForm" ng-if="!complete">
<div ng-repeat="i in getNumber(selectedItem.number) track by $index">
{{$index}}
</div>
</form>
Complete is set to false in the beginning, and hitting a Next button will toggle complete and hide the form and dropdown. A Back button will then toggle complete back, and show the form again.
The problem I'm having is with the ng-if on the select (and previously, I had the form wrapped in a div with the same ng-if - same problem). The ng-repeat no longer updates when the select dropdown is changed. Removing the ng-if on the select restores the ng-repeat to working order.
I'm wondering if there's something strange I'm doing with the nesting here, or if it's actually a bug? You can test it out on the JSFiddle linked above. The $index should be printed the number of times on the dropdown, but isn't.
Interestingly enough - when debugging the problem on my local machine, having FireBug open fixed the issue.
This is because of ng-if creating a child scope and how prototypical inheritance works with primitives. In this case, the primitive is selectedItem that you are setting by the <select>, but is actually being set on the child scope and shadows/hides the parent scope property.
In general you should always use a dot (.) with ng-models:
$scope.selection = {selectedItem: undefined};
And in the View:
<div ng-if="!complete">
<select ng-model="selection.selectedItem"
ng-options="item.name for item in items"></select>
</div>
ng-if is causing you some scoping issues (which messes with the binding).
Here is an updated jsfiddle that you could use as a work around. Essentially, this example wraps another div around the items that you want to end up hiding. And then adds a next function so that the same scope is affected during the click that sets complete to true.
HTML:
<div ng-app="test">
<div ng-controller="TestCtrl">
<div ng-if="!complete">
<div>
<label for="testAmount">Amount:</label>
<select id="testAmount" ng-model="selectedItem" ng-options="item.name for item in items"></select>
</div>
<form role="form" name="testForm">
<div ng-repeat="i in getNumber(selectedItem.number) track by $index">
{{$index + 'hi'}}
</div>
<button class="btn btn-default" value="Next" title="Next" ng-click="next()">Next</button>
</form>
</div>
<div ng-if="complete">
</div>
</div>
</div>
JS:
angular.module('test', [])
.controller('TestCtrl', function($scope) {
$scope.complete = false;
$scope.items = [
{ name: '2', number: 2 },
{ name: '3', number: 3 },
{ name: '4', number: 4 }
];
$scope.selectedItem = $scope.items[0];
$scope.getNumber = function (number) {
return new Array(number);
};
$scope.next = function() {
$scope.complete = true;
};
})
I believe the problem is with your select statement inside an ng-if the selectedItem is never getting set. If you just don't want to show that dropdown when !complete change it to an ng-show and it works fine.
<div ng-show="!complete">
As to WHY the ng-model is not being bound inside the ng-if, I don't really know but it does make some sense in that you are trying to do a conditional bind which is a bit screwy

Load angular template on some event

I'm quite new to angular and frontend in general, but what i'd like to see is something similar to what routing with ngView gives, but without routing, i.e just load a template on some event. To be more specific, let's say i have an input field somewhere in the header and when i click/focus on this field a special panel with different input options shows up. The trick is that this input field and other elements are already a part of a template which is loaded into ngView, so as i understand i can't use another ngView for options pane.
use ngIf, ngShow, ngHide, ngSwitch for stuff like that
<button ng-click="showStuff = true">Show Stuff</button>
<button ng-click="showStuff = false">Hide Stuff</button>
<div ng-show="showStuff">Showing Stuff</div>
<div ng-hide="showStuff">Hiding Stuff</div>
Have a look at this plunker for a quick and dirty, working example.
Note that the showStuff variable is just magically created by angular on the root scope, since I'm not using a controller.
You can load templates with ng-if and ng-include like this example:
<body ng-app="app">
<div class='container'>
<button ng-click='tmpl = true' class='btn btn-info'>Load template!</button>
<div ng-if='tmpl'>
<div ng-include="'template.html'"></div>
</div>
</div>
</body>
The ngIf directive will add element to the DOM when the argument expression is true. Then, the angular will compile the inner directive ngInclude, loading the template.

how to get a item inside item in html angular js?

I tried get a value from both dynamic objects in angular js
<div ng-controller="SampleController">
<div> {{item['111']['price']}}
</div>
inside SampleController
$scope.item={111:{price:"232"},112:{price:"233"},115:{price:"237"}};
right now I put item['111']['price'] statically. if when i receive the value dynamically from some where else how to that.
Like,
<div ng-controller="SampleController">
<div> {{item[{{ItemId['id']}}]['price']}}
</div>
$scope.ItemId={id:111};
$scope.item={111:{price:"232"},112:{price:"233"},115:{price:"237"}};
But its returning error. I tried with route scope also.Any one please help out.
Try this:
<div>{{item[ItemId.id].price}}</div>

Editing and saving is not working

I have created an application in AngularJS with edit, save and cancel options, but the problem is that when I click the edit I am not getting the value for editing and saving.
The textfield and dropdowns are been provided through ng-transclude
Can anyone please tell me some solution for this
DEMO
HTML
<div ng-controller="LocationFormCtrl">
<h2>Editors</h2>
<span ng-repeat="location in location">
<div class="field">
<strong>State:</strong>
<div click-to-edit="location.state"><input ng-model="view.editableValue"/></div>
</div>
<div class="field">
<strong>City:</strong>
<div click-to-edit="location.city"><select ng-model="view.editableValue" ng-options="loc.city for loc in location"></select></div>
</div>
<div class="field">
<strong>Neighbourhood:</strong>
<div click-to-edit="location.neighbourhood"><input ng-model="view.editableValue"/></div>
</div>
<h2>Values</h2>
<p><strong>State:</strong> {{location.state}}</p>
<p><strong>City:</strong> {{location.city}}</p>
<p><strong>Neighbourhood:</strong> {{location.neighbourhood}}</p>
<hr>
</span>
</div>
Don't really know why, I was just playing around with the code, but seems working, at least with the text fields, using ng-if instead of ng-show/ng-hide: http://jsfiddle.net/T6rA9/1/
I'll update my answer if I find a reason...
Update: I think this is what you're looking for: http://jsfiddle.net/T6rA9/7/
The difference is that instead of saving the value on save, I am reverting the changes on cancel, which is easier due to angular two-way data-binding.
Because of that, I also removed the view.editableValue ng-model directive and used the fields as you would normally do.
Transclusion and isolated scopes does not work the way you may think. You can read more about it here http://angular-tips.com/blog/2014/03/transclusion-and-scopes/
If you i.e. make this change you will already see a difference
<div click-to-edit="location.state"><input ng-model="location.state"/></div>
What about creating ngClick function which add input element inside your div with previous value?
<div class="newInput" ng-show="hidden">
<label> {{ inputValue }} </label>
</div>
<div class="newInput" ng-show="!hidden">
<input ng-model="inputValue" />
</div>
And main.js file:
app.controller('MyCtrl', function($scope) {
$scope.hidden = true;
$scope.inputValue = 'Edit me!';
$scope.addInput = function() {
$scope.hidden = !$scope.hidden;
}
});
Here you have Plunker

Categories