angularjs filters unique filters - javascript

How to enable or disable the radio buttons according to available options in the array
// Code goes here
var app = angular.module('app', ['ui.directives','ui.filters']);
app.controller('ctrl', function($scope, $filter,$http) {
$scope.pageNumber = {};
$http.get('https://cdn.rawgit.com/rainnaren/20355aea389ba6f7bfb801ecb52774d6/raw/4482a3d9f5a0cc3e73720a11e0e2b60c085519c0/data.json').then(function(data){
$scope.data = data.data;
angular.forEach($scope.data.products,function(key,value){
angular.forEach(key.productAttributes,function(k,val){
// console.log(key.productAttributes)
// $scope.brandsGroup = uniqueItems(key.productAttributes, val);
// console.log($scope.brandsGroup)
})
})
});
// var uniqueItems = function (data, key) {
// var result = [];
// for (var i = 0; i < Object.keys(data).length; i++) {
// var value = data[i][key];
// if (result.indexOf(value) === -1) {
// result.push(value);
// }
// }
// return result;
// };
$scope.$watch(function() {
return $scope.pageNumber;
}, function() {
$scope.v = function(event,d) {
var count = Object.keys($scope.pageNumber.productAttributes).length;
console.log(count);
if ($scope.data.variantAttributeses.length === count) {
$scope.x = $filter('filter')($scope.data.products, $scope.pageNumber);
}
};
});
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.min.js"> </script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="ctrl">
{{pageNumber}}
<div ng-repeat="d in data.variantAttributeses | unique:d">
{{d.name}}
<div>
<form ng-repeat="dg in data.products | filter:pageNumber ">
<label><input ng-change="v()" type="checkbox" ng-model="pageNumber.productAttributes[d.name]" ng-true-value="'{{dg.productAttributes[d.name] }}'" ng-false-value="''">{{dg.productAttributes[d.name] }}</label>
</form>
</div>
</div>
<div>
<div ng-repeat="data in x | filter:pageNumber:true">
{{data.brandProductId}}
</div>
</div>
</body>
</html>
here the unique filter is not working what is the solution to do this i tried the angular ui filters but in my case it is not working anyone provide me the custom filter for that.
in this the field name is also dynamic . so how to filter the duplicates from the json
here is my working code

The logic for writing the function that determines what is disabled isn't trivial (I just tried for about 15 minutes) ultimately you can use ng-disabled and set a property on the "option" in the data so that it gets reflected in the view, something like
ng-disabled="d.disabled"
ng-change="checkDisabled()"
in the checkDisabled you'd have to run the logic to determine which options actually get the "disabled" attribute added to them for use by ng-disabled here.
Also to keep the filtered data on scope can use:
<div ng-repeat="data in data.products | filter:pageNumber as filtered">
then you will have a $scope.filtered with the filtered products. The trick is you need to go through all radio options and for each one you need to search all products and see if any product doesn't match the option value. If it matches any value then disabled for that option =false if it matches no values of any or the filtered products then it's disabled=true.

Related

Change value on second select and keep values

Hello I would like to load data options of the 2nd select from mysql when I click on a value of the first selectors.
And keep the JSON data of the last fields selected and keep append function.
I know how to import data from mysql, but I Would like to get Values each time I change the first selectors without changing all second selectors, only the concerned selector.
How it works.
I select a category ( not shown in the code )
the most important:
The select 1 receive all categories of category selected.
The select 2 receive all categories of select 1 subcategory
when the 1first category is changed, the 2nd selector are loaded but don't forget I need to add unlimited fields without changing all 2nd selectors
im using this code:
https://plnkr.co/edit/kKjhpy0fdnOprFA8PAYx?p=preview
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="appCtrl">
<h3>Add Input fields dynamically</h3>
<button ng-click="addSelectItem()">Add select Field</button>
<div ng-repeat="item in selects">
<select ng-model="item.type"><option ng-repeat='option1 in type' value='{{option1.nomcarac}}' >{{option1.nomcarac}}</option></select>
<select ng-model="item.brandname" ><option ng-repeat='option1 in valuelist' value='{{option1.nomcarac}}' >{{option1.nomcarac}}</option></select>
<button ng-click="getValue(item)">get input value</button>
</div>
<pre>{{inputs | json}}</pre>
<pre>{{selects | json}}</pre>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('appCtrl', function($scope) {
$scope.inputs = [];
$scope.selects = [];
$scope.type = [{nomcarac: "phone"},{nomcarac: "shoes"}]
$scope.phonelist = [{nomcarac: "apple"},{nomcarac: "motorola 10g"}]
$scope.valuelist = [{nomcarac: "test"},{nomcarac: "test2"}]
$scope.shoeslist = [{nomcarac: "jean michel"},{nomcarac: "motorola 10g"}]
var count = 1;
var fieldname;
$scope.addItem = function(){
fieldname = "Field " + count;
$scope.inputs.push({name: fieldname});
count++;
}
$scope.addSelectItem = function(){
fieldname = "Field " + count;
$scope.selects.push({name: fieldname});
count++;
}
$scope.getValue = function(item){
alert(item.value);
}
});
</script>
</body>
</html>
If I understood you correctly, you want to populate options of the second select every time, you change the value of the first select in the group.
If so, you can use ngChange to accomplish this and store the values list within the corresponding item object:
var app = angular.module('myApp', []);
app.controller('appCtrl', function($scope) {
$scope.inputs = [];
$scope.selects = [];
$scope.type = [{nomcarac: "phone"}, {nomcarac: "shoes"}];
$scope.phonelist = [{nomcarac: "apple"}, {nomcarac: "motorola 10g"}];
$scope.shoeslist = [{nomcarac: "jean michel"}, {nomcarac: "gucci"}];
var count = 1;
var fieldname;
$scope.addItem = function(){
fieldname = "Field " + count;
$scope.inputs.push({name: fieldname});
count++;
};
$scope.addSelectItem = function(){
fieldname = "Field " + count;
$scope.selects.push({name: fieldname});
count++;
};
$scope.getValue = function(item){
console.log(item);
};
$scope.getValuesList = function(item) {
//get actual data from db
switch (item.type){
case 'phone':
item.valuelist = angular.copy($scope.phonelist);
break;
case 'shoes':
item.valuelist = angular.copy($scope.shoeslist);
break;
default:
item.valuelist = [];
break;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="appCtrl">
<h3>Add Input fields dynamically</h3>
<button ng-click="addSelectItem()">Add select Field</button>
<div ng-repeat="item in selects">
<select ng-model="item.type" ng-change='getValuesList(item)'>
<option ng-repeat='option in type' value='{{::option.nomcarac}}' >{{::option.nomcarac}}</option>
</select>
<select ng-model="item.brandname">
<option ng-repeat='option in item.valuelist' value='{{::option.nomcarac}}' >{{::option.nomcarac}}</option>
</select>
<button ng-click="getValue(item)">get input value</button>
</div>
<pre>{{inputs | json}}</pre>
<pre>{{selects | json}}</pre>
</div>

AngularJS Checkbox Rendering Very Slow the First Time

I'm having an issue with a legacy app that's running Angular 1.5.9. The controller contains the following loop which is triggered by a "Select All" link on the page:
var len = $scope.payments.length, i;
for (i = 0; i < len; i++) {
$scope.payments[i].selected = true;
}
The selected property in the objects in the payments array is bound to checkboxes in the view:
<tr data-ng-repeat="payment in payments | orderBy: 'payDate'">
<td><input type="checkbox" data-ng-model="payment.selected" data-ng-change="setSelectedTotal()"/>...
There are up to 15000 items in the array/rows in the table, and the first time the Select All link is clicked after page load it takes up to 40 seconds for the view to refresh with all of the checkboxes checked. If I clear the checkboxes and then click the Select All link again, the checkboxes show as selected in about 1 second or less. This is true on all subsequent clicks of the Select All link-it's only slow the first time but takes a second or less every time after. I suspect this is related to something going on with model binding because when I surround the loop with console.time() and console.timeEnd(), the loop only takes a couple of milliseconds even on the first try. So the issue is with something that's happening after the loop completes. I've tried switching from ng-model to ng-checked just to see if it would speed things up but it gives me an error, and actually the app depends on the checkboxes being bound to the selected property. I also tried running a select all (followed by a clear all) on the first thousand checkboxes on page load but that didn't make any difference. Any insight into why it's so slow the first time and/or how to speed it up would be greatly appreciated.
Here is an example with some optimizations.
Note : I made use of document.querySelectorAll to select/unselect outside of controller as it's much faster than relying on $scope data.
angular.module('app', []);
angular.module('app')
.controller('ExampleController', ['$scope', function($scope) {
$scope.payments = [];
$scope.selected = false;
$scope.total = 0;
$scope.itemsCount = 7500;
// Populate with
populate($scope.itemsCount);
$scope.updateTotal = function() {
let total = 0;
for (let i = 0; i < $scope.payments.length; i++) {
if ($scope.payments[i].selected === true) {
total += $scope.payments[i].amount;
}
}
$scope.total = total;
}
$scope.toggleAll = function() {
// Toggle global selected state
$scope.selected = !$scope.selected;
for (let i = 0; i < $scope.payments.length; i++) {
$scope.payments[i].selected = $scope.selected;
}
$scope.updateTotal();
}
$scope.toggle = function(index) {
$scope.payments[index].selected = !$scope.payments[index].selected;
$scope.updateTotal();
}
function populate(count) {
for (let i = 0; i < count; i++) {
$scope.payments.push({
amount: i,
selected: false
});
}
}
}]);
// Toggle all checkbox
function vanillaToggleAll(event) {
var el = event.srcElement || event.target;
var checkboxes = document.querySelectorAll("input[type='checkbox']");
for (let i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = el.checked;
}
}
<!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.4/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="ExampleController">
<h1>Items: {{itemsCount}}, Total: {{total}} USD</h1>
<table>
<thead>
<tr>
<td>
<input type="checkbox" ng-click="toggleAll()" onclick="vanillaToggleAll(event)">
<label>Select/Unselect All</label>
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="payment in payments | orderBy: 'amount'">
<td>
<input type="checkbox" class="checkbox" ng-bind="payment.selected" ng-click="toggle($index)" />
<label ng-bind="::payment.amount"></label> USD
</td>
</tr>
</tbody>
</table>
</body>
</html>
A demo plunker with 7500 items to play with
And here are the results, I've used Chrome profiler to analyse time spent for loading, scripting, rendering...
1000 items
10000 items
15000 items

Force custom filter to work in repeat

I need to use filter in my loop.
Let's say that we have simple array with names: ['Thomas', 'Brian', 'Joana']. I want to view filtered set of names. It works as expected when I use Angular's filter:
<input ng-model="filterText" />
<span ng-repeat="name in names | filter:filterText">{{name}}</span>
but when I want to use some custom filter method it doesn't work when value of 'filterText' input is changed:
<input ng-model="filterText" />
<span ng-repeat="name in names | filter:filterMethod">{{name}}</span>
In js file:
$scope.filterMethod = function(item) {
if ($scope.textFilter==item || $scope.textFilter==null) {
return true;
}
return false;
}
I want to force filtering action on list of names alway when user change 'filterText' input, but actually this list is changed only if it is filtered by Angular predefined filter. Complete plnkr example: plnkr
Implement the custom filter like this
$scope.filterMethod = function(name) {
return function(item){
if(!name ) return item;
if (name && item.startsWith(name)) {
return item;
}
}
}
and change call the filter in the html like this
<span ng-repeat="name in result = (names | filter:filterMethod(filterText))">
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.names = ['Thomas', 'Brian', 'Joana'];
$scope.filterMethod = function(name) {
return function(item){
if(!name ) return item;
if (name && item.startsWith(name)) {
return item;
}
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<input ng-model="filterText" />
<span ng-repeat="name in result = (names | filter:filterMethod(filterText))">
{{name}}
</span>
</div>
You probably need custom filter:
.filter('customFilter', function() {
return function(items, searchText) {
var filtered = [];
//logic
return filtered;
}
});
<span ng-repeat="name in names | customFilter:text">{{name}}</span>
Change $scope.textFilter to $scope.filterText
$scope.filterMethod = function(item) {
if ($scope.textFilter==item || $scope.textFilter==null) {
return true;
}
return false;
}
Here is a fork to your plunkr
http://plnkr.co/edit/a3uSyez0VFGbZ5ZARcu7?p=preview

Not able to understand the deleting process while writing todo list in AngularJS

I am trying to write a todo application in Angularjs in the following code.
function write_controller($scope){
$scope.todos = [{text:'hey all',done:false},
{text:'hello',done:false}];
$scope.addtodo = function(){
$scope.todos.push({text:$scope.todopush,done:false});
$scope.todopush = '';
}
$scope.delete = function(){
var oldtodos = $scope.todos;
$scope.todos = [];
angular.forEach(oldtodos, function(x){
if (!x.done){
$scope.todos.push(x);}
});
};
}
<html ng-app>
<head>
<script src =
"https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js">
</script>
</head>
<body>
<div class = "basic_class" ng-controller = "write_controller">
<ul>
<li ng-repeat = "todo in todos"><input type = "checkbox" ng-model
="todo.done">{{todo.text}}</input></li>
</ul>
<input type = "text"
placeholder = "please add data here"
ng-model="todopush">
</input>
<input type = "button" ng-click ="addtodo()" value ="Click me!!"></input>
<input type = "button" ng-click = "delete()" ng-model="remove" value =
"remove!"></input>
</div>
</body>
</html>
In the following code ,I have the following questions.
How is the delete operation working??
My understanding:
1)It pushes the existing array into a new array
2)It clears the exisitng array
3)Iterates over the new array
3)Checking the done functionality??? (When it says !x.done , is it true or false???)
Any help would be highly appreciated.
Walk through the steps
$scope.delete = function() {
// store existing todos array in variable
var oldtodos = $scope.todos;
// create new empty array for todos
$scope.todos = [];
// loop over previously stored todos
angular.forEach(oldtodos, function(x) {//x is element of the array - a single todo object
// if x.done is not truthy
if (!x.done){
// push this item into `$scope.todos`
$scope.todos.push(x);
});
}
Basically it only pushes the done:false into new version of $scope.todos which effectively removes the done:true

Function in angular expression not updating when parameter has changed

Here is a simplified example of what I'm trying to do.
(function(){
var app=angular.module('Tester',[]);
app.controller('TestController',function($scope){
$scope.days=[{name:'Sun'},{name:'Mon'},{name:'Teu'},{name:'Wed'},{name:'Thu'},{name:'Fri'},{name:'Sat'}];
//if I is use `days=['Sun','Mon'...]` it works
$scope.values={};
$scope.add=function(values){
var sum=0;
$scope.days.map(function(v){
v=values[v];
if(v){
sum+=(v-0);
}
});
return sum;
}
});
app.filter('sum',function(){
return function(obj){
var total=0;
for(var v in obj){
total+=(obj[v]-0)||0;
}
return total;
}
});
})()
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Tester">
<div ng-controller="TestController as test">
<input ng-model="values[day.name]" value="{{values[day.name]||0}}" ng-repeat="day in days">
<div>{{add(values)}}</div>
<div>{{values | sum}}</div>
</div>
</div>
Basically I want to have a row of inputs and a total to show the sum. It works if I use days=['Sun','Mon'...] or a filter. But the filter seems semantically incorrect as well as not allowing me to add other properties to the values object (value={'Mon':2,'time':123456789} would give an incorrect sum) and days=[{name:'Sun'}...] allows me to store more information than days=['Sun','Mon'...] about each day.
You need to edit your add function a bit, changing v=values[v] to v=values[v.name] inside the inner map function.
This is because your days array now contains objects ({name: 'Mon'} etc), so...
$scope.days.map(function (v) {
// in here v = {name: 'Mon'}, not 'Mon' as previously,
// but the values object still has day names as keys:
// {'Sun': 2, 'Mon': 1} etc.
// --> values[v] === undefined, but values[v.name] matches
})
Below is the edit in place, and it works as I presume you wanted it to work. Oh, and I added the same (v-0)||0 trick to the sum calculations, so that entering invalid data (text for example) doesn't break it up.
(function(){
var app=angular.module('Tester',[]);
app.controller('TestController',function($scope){
$scope.days=[{name:'Sun'},{name:'Mon'},{name:'Teu'},{name:'Wed'},{name:'Thu'},{name:'Fri'},{name:'Sat'}];
//if I is use `days=['Sun','Mon'...]` it works
$scope.values={};
$scope.add=function(values){
var sum=0;
$scope.days.map(function(v){
v=values[v.name];
if(v){
sum+=(v-0)||0;
}
});
return sum;
}
});
app.filter('sum',function(){
return function(obj){
var total=0;
for(var v in obj){
total+=(obj[v]-0)||0;
}
return total;
}
});
})()
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Tester">
<div ng-controller="TestController as test">
<input ng-model="values[day.name]" value="{{values[day.name]||0}}" ng-repeat="day in days">
<div>{{add(values)}}</div>
<div>{{values | sum}}</div>
</div>
</div>

Categories

Resources