AngularJS, ng-repeat with condition - angularjs

I'm new in AngularJS (2 days). I have this code:
<tr class="factoring-grid__row fixed_row" ng-if="vm.filteredXml.length > 0" ng-class="{disabled: vm.disableMyData(item)}"
ng-repeat="(index, item) in vm.filteredXml">
<td>{{item.receptor.razonSocial}}</td>
<td>{{item.folio}}</td>
<td style="text-align: center">
<div class="form-group datetime" style="display: flex">
<div class="factoring-grid__date-picker">
<input type="text" autocomplete="off" class="form-control input-sm" uib-datepicker-popup="{{vm.format}}"
ng-model="vm.filteredXml[index].fechaVencimiento" is-open="vm.datePickerList[index].isOpen"
datepicker-options="vm.dateOptions" current-text="Hoy" close-text="Cerrar" clear-text="Reset"
alt-input-formats="vm.altInputFormats" popup-placement="top-right" style="width: 100%;" />
</div>
<span ng-click="vm.openDatePicker(index)" class="calendar-icon"></span>
</div>
</td>
<td>
<span>{{item.montoTotal | filterPesoChile}}</span>
</td>
</tr>
I need to filter the data, I mean, those item have a propertie called item.status so I need to avoid to render as a the items where item.status === 'deleted'. Should I filter right here that condition? or should I filter the data that use this ng-repeat (vm.filteredXml`).
I'm not used to angularjs directives. In reactjs I just simply map or filter the array of data and return each , but don't know how to to that with ng-repeat

Here is a sample snippet using a directive and a dedicated filter with an optional status (default is disabled)
The directive template is embedded because I cannot add an external file in a StackOverflow snippet.
(function () {
'use strict';
angular.module('app', []);
angular
.module('app')
.directive('items', function () {
return {
restrict: 'EAC',
scope: {},
template: '<ul><li ng-repeat="item in vm.items|excludedItemsFilter:\'disabled\'">{{item.label}}</li></ul>',
link: link,
controller: controller,
controllerAs: 'vm'
};
function link(scope, element, attrs) {
scope.$on('$destroy', function () {
// destroy events binded to $rootScope,
// cancel $interval and $timeout timers
});
}
function controller($scope) {
var vm = this;
vm.items = [
{label: "Item 1", status: "enabled"},
{label: "Item 2", status: "enabled"},
{label: "Item 3", status: "disabled"},
{label: "Item 4", status: "enabled"},
{label: "Item 5", status: "disabled"}
];
}
});
angular
.module('app')
.filter('excludedItemsFilter', function () {
return function (items, excludedStatus) {
excludedStatus = excludedStatus || 'disabled'; // default value
return items.filter(function (item) {
return item
&& item.status !== excludedStatus;
});
}
});
})();
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script src="module.js"></script>
</head>
<body>
<div items></div>
</body>
</html>
You can also remove the dedicated filter and filter items in directive like this :
angular.module("app").directive("items", function () {
return {
restrict: "EAC",
scope: {},
template: '<ul><li ng-repeat="item in vm.items">{{item.label}}</li></ul>',
link: link,
controller: controller,
controllerAs: "vm",
};
function link(scope, element, attrs) {
scope.$on("$destroy", function () {
// destroy events binded to $rootScope,
// cancel $interval and $timeout timers
});
}
function controller($scope) {
var vm = this;
vm.items = [
{ label: "Item 1", status: "enabled" },
{ label: "Item 2", status: "enabled" },
{ label: "Item 3", status: "disabled" },
{ label: "Item 4", status: "enabled" },
{ label: "Item 5", status: "disabled" },
].filter(function (item) {
return item && item.status !== "disabled";
});
}
});

Related

Unable to show content of array as checkboxes using ng-repeat

I have the following in my controller:
var myApp = angular.module("myApp", []);
myApp.controller("TestCtrl", ['$scope', function($scope) {
$scope.rows = [
'Facebook',
'Twitter',
'Pinterest',
'Instagram',
'Tumblr',
'Google'
];
}]);
and I'm trying to show the content like this
<div class="container">
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<label ng-repeat="row in rows">
<input type="checkbox" ng-checked="row.selected" ng-model="row.selected" />{{row}}</label>
</div>
</div>
right now the items show, but I can't check the checkboxes,
check this Plunker
In order to have your checkbox checkable, you need to pass a valid ng-model there. In your case, row.selected is invalid since every row is a string and not object.
You can have your $scope.rows array like this instead:
$scope.rows = [{
name: 'Facebook',
selected: false
}, {
name: 'Twitter',
selected: false
}, {
name: 'Pinterest',
selected: false
}, {
name: 'Instagram',
selected: false
}, {
name: 'Tumblr',
selected: false
}];
Here's a forked plunker which has checkboxes checkable

Angular Radio Button Not Firing On Watch

I have a watch on region but it is not firing when I click on the radio button.
Am I doing something wrong or is it because radio buttons only detect change once in angular? Anyway around this without using form?
<div class="filter-column">
<div class="filter-title">Region</div>
<div class="bottom-line"></div>
<div class="overflow-container">
<div ng-repeat="choice in regions| orderBy: 'description'">
<input type="radio"
value="{{choice.name}}"
name="regionRadio"
ng-model="region">
{{choice.description}}
</div>
</div>
</div>
$scope.$watchCollection(watchRMDapisPopulate,
populateRMDfiltersView);
function watchRMDapisPopulate() {
return regionMarketDealerSrv.orgFilterData;
}
function populateRMDfiltersView(newValue, oldValue) {
if (newValue) {
$scope.regions = newValue.regions;
}
}
$scope.$watch('region', radioButtonRegion);
function radioButtonRegion(regionName) {
console.log(regionName)
if (regionName === 'All') {
regionMarketDealerSrv.populateRegions();
} else {
regionMarketDealerSrv.populateMarkets(regionName);
}
}
The watch isn't able to pick up the changes correctly when using ng-model="region" since you are using primitive values. When you change the value you are getting a new reference. You can use a property of an object as your model and $watch that:
var app = angular.module('app', [])
app.controller('MyController', function($scope) {
$scope.regions = [{
name: 'a',
description: 'region A'
}, {
name: 'b',
description: 'region B'
}];
$scope.selected = {
region: 'a'
};
$scope.$watch('selected.region', radioButtonRegion);
function radioButtonRegion(newVal, oldVal) {
if (newVal !== oldVal) {
console.log(newVal, oldVal)
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyController">
<div>Region</div>
<div ng-repeat="choice in regions| orderBy: 'description'">
<input type="radio" value="{{choice.name}}" name="regionRadio" ng-model="selected.region">{{choice.description}}
</div>
</div>

How to use HTML inside conditional bind in markup

I have markup like this
<p>{{ !job.AdditionalNotes ? "No additional notes." : job.AdditionalNotes }}</p>
Would like to emphasis No Additional notes using something like.
<p>{{ !job.AdditionalNotes ? <em>"No additional notes."</em> : job.AdditionalNotes }}</p>
Is there a way to do this without using ng-if and ng-show to do this retaining the ternary operator?
1st Option
I get this working in the following way (without ng-show or ng-if). I'm using ng-bind-html and $sce service to render the HTML. Since your "no additional notes" message is generic and common, we can easily define in the controller and get it from a method after sanitization.
var app = angular.module("sa", []);
app.controller("FooController", function($scope, $sce) {
$scope.jobs = [{
name: "Sr. Software Developer"
}, {
name: "Software Associates",
AdditionalNotes: "Remote location"
}, {
name: "Front-end developer"
}];
$scope.trust = function(text) {
return $sce.trustAsHtml(text);
};
$scope.noNotesMessage = function() {
return $scope.trust("<em>No additional notes.</em>")
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sa" ng-controller="FooController">
<ol>
<li ng-repeat="job in jobs">
<strong>{{job.name}}</strong>
<p ng-bind-html="!job.AdditionalNotes ? noNotesMessage() : trust(job.AdditionalNotes)"></p>
</li>
</ol>
</div>
2nd Option
Alternatively, you can write a directive:
var app = angular.module("sa", []);
app.controller("FooController", function($scope, $sce) {
$scope.jobs = [{
name: "Sr. Software Developer"
}, {
name: "Software Associates",
AdditionalNotes: "Remote location"
}, {
name: "Front-end developer"
}];
});
app.directive('notes', function() {
return {
restrict: 'E',
scope: {
additional: '='
},
link: function($scope, element, attr) {
var html = "<p>" + ($scope.additional || "<em>No additional notes.</em>") + "</p>";
element.html(html);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sa" ng-controller="FooController">
<ol>
<li ng-repeat="job in jobs">
<strong>{{job.name}}</strong>
<notes additional="job.AdditionalNotes"></notes>
</li>
</ol>
</div>

How to get multiple selected check box values

How to get multiple selected check box values in Angular.js and insert into database separated with a comma (,) ?
You can use ng-repeat + ng-model over an array of options.
DEMO http://plnkr.co/edit/KcUshc74FZL1npZsKbEO?p=preview
html
<body ng-controller="MainCtrl">
<div class="container">
<h1>Options</h1>
<div>
<div class="form-group" ng-repeat="option in options">
<label>{{option.name}}</label>
<input type="checkbox" ng-model="option.value">
</div>
</div>
<hr>
<button class="btn btn-primary" ng-click="save()">save to database</button>
</div>
</body>
js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.options = [{
name: 'java',
value: true,
}, {
name: 'c#',
value: false
}, {
name: 'angular',
value: true
}, {
name: 'r',
value: false
}, {
name: 'python',
value: true
}, {
name: 'c++',
value: true
}];
$scope.save = function() {
var optionsCSV = '';
$scope.options.forEach(function(option) {
if (option.value) {
// If this is not the first item
if (optionsCSV) {
optionsCSV += ','
}
optionsCSV += option.name;
}
})
// Save the csv to your db (replace alert with your code)
alert(optionsCSV);
};
});

AngularJS: Custom directive using dynamic attribute value doesn't work inside "ng-repeat"

Could you explain please why the following directive doesn't work?
attrs.ngMydirective seems to be undefined inside the linking function.
Live example here
HTML:
<body ng-controller="MyCtrl">
<ul>
<li ng-repeat="person in people">
{{ person.name }}
<span ng-mydirective="{{ person.age }}"></span>
</li>
</ul>
</body>
JS:
var app = angular.module('myApp', []);
app.directive('ngMydirective', function() {
return {
replace: true,
link: function(scope, element, attrs) {
if (parseInt(attrs.ngMydirective, 10) < 18) {
element.html('child');
}
}
};
});
app.controller('MyCtrl', function($scope) {
$scope.people = [
{name: 'John', age: 33},
{name: 'Michelle', age: 5}
];
});
You should use attrs.$observe to have actual value.
Another approach is to pass this value to directive's scope and $watch it.
Both approaches are shown here (live example):
var app = angular.module('myApp', []);
app.directive('ngMydirective', function() {
return {
replace: true,
link: function(scope, element, attrs) {
attrs.$observe('ngMydirective', function(value) {
if (parseInt(value, 10) < 18) {
element.html('child');
}
});
}
};
});
app.directive('ngMydirective2', function() {
return {
replace: true,
scope: { ngMydirective2: '#' },
link: function(scope, element, attrs) {
scope.$watch('ngMydirective2', function(value) {
console.log(value);
if (parseInt(value, 10) < 18) {
element.html('child');
}
});
}
};
});
app.controller('MyCtrl', function($scope) {
$scope.people = [
{name: 'John', age: 33},
{name: 'Michelle', age: 5}
];
});
<body ng-controller="MyCtrl">
<ul>
<li ng-repeat="person in people">
{{ person.name }}
<span ng-mydirective="{{ person.age }}"></span>
</li>
<li ng-repeat="person in people">
{{ person.name }}
<span ng-mydirective2="{{ person.age }}"></span>
</li>
</ul>
</body>

Resources