ng hide/show based on list values - angularjs

I need to hide the "Current insurance cover" when coverAmt of all the covers in the list are zero or negative value. If any one coverAmt in the list is positive value then I need show the "Current insurance cover" only once.
I tried with something like this, but now no luck..!
<li ng-repeat="cover in accSummary.response.covers">
<div class="account-detail-row col-xs-12 col-sm-12 col-md-12 padding-left12 padding-right12 padding-top24 padding-bottom12">
<h4 class="font-16 fontwt-400" ng-hide="cover.coverAmt <= 0">Current insurance cover</h4>
</div>
</li>
can anybody please help me on this..! thanks.

You have to calculate this in your controller as below:
app.controller("cover", function($scope){
$scope.covers = [{coverAmt: 10},{coverAmt: 0},{coverAmt: -1}];
$scope.showHeading = function(){
var flag = false;
for(var i=0; i<$scope.covers.length; i++)
{
if($scope.covers[i].coverAmount > 0)
{
flag = true;
break;
}
}
return flag;
};
});
HTML will be
<h4 class="font-16 fontwt-400" ng-show="showHeading();">Current insurance cover</h4>

Try using ```ng-if`` to control the visibility of the Current Insurance Cover. But on the init of the ng-repeat, run a call to loop through the array to test your case.
Below is a sample of what this would look like:
HTML:
<li ng-repeat="cover in accSummary.response.covers" ng-init="checkCover()">
<div class="account-detail-row col-xs-12 col-sm-12 col-md-12 padding-left12 padding-right12 padding-top24 padding-bottom12">
<h4 class="font-16 fontwt-400" ng-if="visible">Current insurance cover</h4>
</div>
</li>
JS:
$scope.visible = false;
$scope.checkCover = function() {
angular.forEach(accSummary.response.covers, function(cover) {
if(cover.coverAmt > 0) { $scope.visible = true; return true; }
}
return false;
}

Firstly if you have the h4 Current insurance cover, within the ng-repeat. If you have multiple positive values, the header will appear multiple times
As for the calculation itself... Rather do that in your controller, then do something like:
<li ng-repeat="cover in accSummary.response.covers">
<div class="account-detail-row">
{{ cover.Something }}
</div>
</li>
<h4 ng-hide="isCurrent">Current insurance cover</h4>
Thus in the success event of the ajax request / promise you could do this:
var total = 0;
$http({ // or whatever request mechanism you're using
url: someURL,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
})
.success(function (data) {
angular.forEach(data.accSummary, function(value, key) {
total += data.accSummary["coverAmt"]
})
})
.finally(function() {
$scope.isCurrent = total <= 0;
})
Or you could create a function and then pass the whole collection through from the view.
Your calculation function could look something like this:
$scope.isCurrent = function(covers) {
var total = 0;
for(var i = 0; i < covers.length; i++){
var cover = covers[i];
total += cover.coverAmt;
}
return total <= 0;
}
Then the usage would be usage:
<h4 ng-hide="isCurrent(accSummary.response.covers)">Current insurance cover</h4>

Related

How to get distinct value using lodash in ReactJS?

How to get distinct value using lodash in ReactJS? Now I'm getting all the data. But how to avoid printing duplicate data? Actually it is a filter box. So data repetition I've to avoid. Can anyone help me out?
Function:
comboClick () {
var apiBaseUrl = "http://api.eventsacross-stage.railsfactory.com/api/";
var input = this.state.search_event;
let self = this;
axios.get(apiBaseUrl+'v1/events/?on_dashboard=false'+input)
.then(function (response) {
let events = response.data.events;
self.setState({events: events});
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
Jsx Part:
<div className="dropdown text-center">
<button
className="btn btn-default dropdown-toggle"
type="button"
data-toggle="dropdown"
style={{width: "50%"}}
onClick={this.comboClick.bind(this)}>
Place
<span className="caret"></span>
</button>
<ul className="dropdown-menu">
{this.state.events.map(function (event, i) {
return (
<div key={i}>
{event.locations.map(function (locations, j) {
return (
<li key={j}><p>{locations.city}</p></li>
)
})}
</div>
)
})}
</ul>
</div>
You can use _.uniqBy, as per documentation:
This method is like _.uniq except that it accepts iteratee which is
invoked for each element in array to generate the criterion by which
uniqueness is computed. The order of result values is determined by
the order they occur in the array. The iteratee is invoked with one
argument: (value).
I've added an example:
var locations =
[
{city:"city1"},
{city:"city2"},
{city:"city3"},
{city:"city1"},
];
var locationsUnique = _.uniq(locations, 'city');
console.log(locationsUnique);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
UPDATE:
From the method shared in the comments I'm guessing that what you want to do is something like:
comboClick() {
var apiBaseUrl = "api.eventsacross-stage.railsfactory.com/api/";
var input = this.state.search_event;
let self = this;
axios.get(apiBaseUrl + 'v1/events/?on_dashboard=false' + input).then(function(response) {
let events = response.data.events;
for (var i = 0; i < response.data.events_count; i++) {
var obj = response.data.events[i];
console.log(obj.locations);
//Assuming that obj.locations has the locations that you want to display
var locationsUnique = _.uniq(obj, 'city'); //Added this line
console.log(locationsUnique); //Added this line
}
for (var j = 0; j <= obj; j++) {}
self.setState({events: events});
}).catch(function(error) {
console.log(error);
});
}

How to "connect" 2 variables in Angular by some value

I have 2 variables in controller:
$scope.first = [
{ id="11", nameF="aaaa1" },
{ id="12", nameF="bbbb1" }
]
$scope.second = [
{ id="21", nameS="aaaa2", idFirst="11" },
{ id="22", nameS="bbbb2", idFirst="12" },
{ id="23", nameS="cccc2", idFirst="12" }
]
In a template I have ngRepeat for variable second:
<div ng-repeat="item in second>
<div>{{item.nameS}}</div>
<div>{{item.idFirst}}</div>
</div>
For every item.idFirst I would like to write out matching nameF instead. What is the best practice to achieve that? I can't seem to figure out a simple way to do it, but suppose there has to be one. Thanx!
You can use custom filter if you don't want to create one single object holding the expected structure.
HTML :
<div ng-repeat="item in second">
<div>{{item.nameS}}</div>
<div>{{item.idFirst | getMatchName:first}}</div>
</div>
JS:
.filter('getMatchName', function() {
return function(strName, arrFirst) {
arrFirst.forEach(function(val, key) {
if (val.id == strName) {
strName = val.nameF;
}
})
return strName;
}
})
Here is working plunker
If I understand correctly,
$scope.getNameF = function(idFirst){
for(var i = 0; i < $scope.first.length; i++){
if($scope.first[i].id === idFirst){
return $scope.first[i].nameF;
}
}
return undefined;
}
<div ng-repeat="item in second">
<div>{{item.nameS}}</div>
<div>{{getNameF(item.idFirst)}}</div>
</div>
EDIT
Also you can prepare data before rendering:
for(var i = 0; i < $scope.second.length; i++){
$scope.second[i].nameF = getNameF($scope.second[i].idFirst);
}
<div ng-repeat="item in second">
<div>{{item.nameS}}</div>
<div>{{item.nameF}}</div>
</div>
You can think of your template logic a bit like code, calling values from other variables: yourValue[another.value].nameF
Change your code to this and it should work
<div ng-repeat="item in second>
<div>{{item.nameS}}</div>
<div>{{first[item.idFirst].nameF}}</div>
</div>

Get model array values in controller's service

I've been facing an issue since couple of hours. My view template looks like-
<div class="row" ng-repeat="row in CampaignsService.getRows().subItems track by $index">
<div class="col-sm-2">
<select class="form-control dropDownPercent" ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" ng-change="CampaignsService.wow(CampaignsService.dropDownPercent, $index)" ng-options="o as o for o in CampaignsService.showPercentDropDown().values">
</select>
</div>
<div class="col-sm-2" style="line-height: 32px">
of visitors send to
</div>
<div class="col-sm-4">
<select class="form-control" ng-model="campaignSelect" ng-options="campaign.Campaign.id as campaign.Campaign.title for campaign in CampaignsService.getRows().items">
<option value=""> Please select </option>
</select>
</div>
<div class="col-sm-4">
<a class="btn btn-default" target="_blank" href="">Show campaign</a>
</div>
Variable CampaignsService.selectCounter is a counter variable and declared in service but when I'm going to use ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" it gives me error -
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 35 of the expression [CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]] starting at [{CampaignsService.selectCounter}}]]
And when I use ng-model="CampaignsService.dropDownPercent['{{CampaignsService.selectCounter}}']" it does not give any error but it takes this variable as string.
My question is how could I create a model array and get model's array values in my service ?? I read many questions in stack community and none of the trick work for me. My service under my script, is
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.dropDownPercent = [];
this.selectCounter = 0;
var gareeb = [];
this.showPercentDefault = 100;
// this.campaignsData = [];
this.$rowsData = {
items: [], //array of objects
current: [], //array of objects
subItems: [] //array of objects
};
this.getRows = function () {
return this.$rowsData;
}
this.addNewRow = function () {
var wowRow = {}; //add a new object
this.getRows().subItems.push(wowRow);
this.selectCounter++;
gareeb.push(0);
}
this.calculatePercentages = function (index) {
angular.forEach(this.getRows().current, function (data, key) {
if (key == index) {
console.log(data);
}
})
}
this.showPercentDropDown = function ($index) {
var balle = 0;
var start;
angular.forEach(gareeb, function (aha, keywa) {
balle += aha;
})
var last = 100 - balle;
var final = [];
for (start = 0; start <= last; start += 10) {
final.push(start);
}
return this.values = {
values: final,
};
}
this.wow = function (valueWa, keyWa) {
console.log(this.dropDownPercent);
gareeb[keyWa] = valueWa;
this.changePercentDropDown();
}
this.changePercentDropDown = function () {
var angElement = angular.element(document.querySelector('.dropDownPercent'));
angular.forEach(angElement, function (data, key) {
console.log(data);
})
}
}])
Target model structure should be
ng-model="CampaignsService.dropDownPercent[1]"
ng-model="CampaignsService.dropDownPercent[2]"
ng-model="CampaignsService.dropDownPercent[3]"
A big thanks in advance.
Since you are in context of the Angular expression, you don't need interpolation tags {{...}}. So ngModel directive should look like this:
ng-model="CampaignsService.dropDownPercent[CampaignsService.selectCounter]"

ng-repeat pagination looses items

I'm learning AngularJS following the good Pro AngularJS written by Adam Freeman.
I'm stuck on ng-repeat pagination using filters. I know there are bootstrap ui directives for Angular, but i'm following this book in order to learn how angular works.
My code:
<section class="row-fluid" ng-controller="GetAjax">
<div class="col-md-12">
<h2>Repater Caricato in Ajax</h2>
</div>
<div class="row-fluid">
<div class="col-md-6" style="max-height: 350px; overflow-y: auto" ng-controller="PagedData">
<ul class="list-group">
<li class="list-group-item" ng-repeat="item in data.visitors | filter:query | range:selectedPage:pageSize">
<b>{{item.id}}.</b> {{item.first_name}} {{item.last_name}} | <small><i>{{item.email}} - {{item.country}} {{item.ip_address}}</i></small>
</li>
</ul>
<ul class="pagination">
<li ng-repeat="page in data.visitors | pageCount:pageSize"
ng-click="selectPage($index + 1)"
ng-class="pagerClass($index + 1)">
<a>{{$index + 1}}</a>
</li>
</ul>
</div>
</div>
</section>
Angular filters
angular.module("customFilters")
/******* Filters per la paginazione dei dati ******************/
//Genera il range di dati in base alla page size
.filter("range", function ($filter) {
return function (data, page, size) {
if (angular.isArray(data) && angular.isNumber(page) && angular.isNumber(size)) {
var start_index = (page - 1) * size;
console.log(data.length);
if (data.length < start_index) {
return [];
} else {
return $filter("limitTo")(data.splice(start_index), size);
}
} else {
return data;
}
}
})
//Calcola il numero di pagine
.filter("pageCount", function () {
return function (data, size) {
if (angular.isArray(data))
{
var result = [];
for (var i = 0; i < Math.ceil(data.length / size) ; i++) {
result.push(i);
}
return result;
}
else
{
return data;
}
}
});
Angular Controller
.controller("GetAjax", function($scope, $http){
$http.get('data/visitors.json').success(function(data) {
$scope.data = {visitors : data};
});
})
.constant("activeClass", "active")
.constant("perPage", 30)
.controller("PagedData", function($scope, $filter, activeClass, perPage){
$scope.selectedPage = 1;
$scope.pageSize = perPage;
console.log("page"+ $scope.selectedPage);
$scope.selectPage = function (newIndex) {
$scope.selectedPage = newIndex;
console.log( {idx: newIndex});
}
$scope.pagerClass = function (index) {
return (index == $scope.selectedPage) ? activeClass : "";
}
});
The result is that after 3 range filter invocations during the page render, the data array looses all the data.
Strange is that using the example from the book this code works perfectly.
Please, help me to know my error :D
splice function overwrites array
if you have an array
a = [1,2,3,4];
a.splice(2,1);
// a = [1,2,4]
results is a = [1,2,4]
use slice instead

AngularJS - ng-repeat show one item at a time

looking for some ideas here. i have a meal plan object that contains an array of meals. only one meal can be set as primary at a time but i want the user to be able to cycle through the array of meals and mark a meal as primary. i am stuck trying to figure out if ngrepeat makes sense here or ngswitch or ngshow. any thoughts or samples would be highly appreciated!
I have tried multiple approaches with no luck.
thanks
You could cycle through the meals by index of the meal and have a button to choose the meal like this:
http://jsfiddle.net/c6RZK/
var app = angular.module('mealsApp',[]);
app.controller('MealsCtrl',function($scope) {
$scope.meals = [
{name:'Meatloaf'},
{name:'Tacos'},
{name:'Spaghetti'}
];
$scope.meal_index = 0;
$scope.meal = {};
$scope.next = function() {
if ($scope.meal_index >= $scope.meals.length -1) {
$scope.meal_index = 0;
}
else {
$scope.meal_index ++;
}
};
$scope.choose = function(meal) {
$scope.meal = meal;
}
});
HTML
<div ng-app="mealsApp" ng-controller="MealsCtrl">
<div ng-repeat="m in meals">
<div ng-if="meal_index == $index">
<strong>{{m.name}}</strong>
<button ng-click="choose(m)">Choose</button>
</div>
</div>
<hr>
<button ng-click="next()">Next</button>
<hr>Your Choice: {{meal.name}}
</div>
You could just attach a property to the plan, with a flag that says whether or not it's the primary plan.
Here's a sample implementation:
$scope.plans = [{name:"One"}, {name:"Two"}, {name:"Three"}];
$scope.selectPlan = function(plan) {
for(var i = 0, l = $scope.plans.length; i < l; i++) {
$scope.plans[i].primary = false;
if($scope.plans[i] === plan) {
$scope.plans[i].primary = true;
}
}
};
HTML:
<ul>
<li ng-click="selectPlan(plan)" ng-repeat="plan in plans" ng-class="{primary: plan.primary}"><a href>{{plan.name}}</a></li>
</ul>
If you'd rather not attach properties you could use something like a selected index property on your controller.

Resources