get checkbox group values in angular watch - angularjs

when tick on each checkbox, i can get all the checked values.
i want to put these values to their respective group.
here are my expected result :
{
'pattern' : ["Plain","Self Design"],
'colour' : ["Blue","Grey"]
}
im using angular $watch to get the selected values.
$scope.$watch('filters|filter:{selected:true}', function (nv, ov, scope) {
$scope.filter_selected = [];
angular.forEach(nv, function (value) {
angular.forEach(value.options, function (v, k) {
if (v.selected == true) {
this.push(v.name);
}
}, $scope.filter_selected);
});
}, true);
here is the full code in fiddle
UPDATE:
i manage to get my expected result with these code :
$scope.$watch('filters|filter:{selected:true}', function (nv, ov, scope) {
$scope.filter_selected = {pattern: [], colour: []};
angular.forEach(nv, function (value) {
if (value.name == 'pattern') {
angular.forEach(value.options, function (v, k) {
console.log(this);
if (v.selected == true) {
this.push(v.name);
}
}, $scope.filter_selected.pattern);
}
if (value.name == 'colour') {
angular.forEach(value.options, function (v, k) {
//console.log(this);
if (v.selected == true) {
this.push(v.name);
}
}, $scope.filter_selected.colour);
}
});
updated fiddle
now, how to make my checking part dynamic if i have more groups?

I have updated your code to simplify what you have above, hopefully achieving the outcome you want. I don't really think you need the watch (unless your update requirements are more complicated), but you should be able to build upon this never the less.
http://jsfiddle.net/j35zt/
The controller code was simplified as follows:
app.controller('FilterCtrl', function ($scope, $http) {
$scope.filters = [
{ name: 'pattern', placeholder: 'pattern',
options: [
{ name: 'Plain', selected: false },
{ name: 'Self Design', selected: false },
{ name: 'Check', selected: false },
{ name: 'Stripe', selected: false },
{ name: 'Print', selected: false }
]},
{ name: 'colour', placeholder: 'colour',
options: [
{ name: 'White', selected: false },
{ name: 'Blue', selected: false },
{ name: 'Grey', selected: false }
]}
];
$scope.updateOutput = function() {
$scope.filter_selected = {};
angular.forEach($scope.filters, function(f) {
$scope.filter_selected[f.name] = [];
angular.forEach(f.options, function(o){
if(o.selected){
$scope.filter_selected[f.name].push(o.name);
}
});
});
}
});
Just note, that the view also needed to be changed to match the controller. Basically ng-change is the sole cause of the updating.

Related

Multi Level JSON Filter

So I have this json:
this.state = {
projects: [{
id: 10,
name: "Project 10",
runTimes: [{
id: 186,
name: "Do Homeworks",
start: "2020-W01",
end: "2020-W09",
project: 10,
users: [{
id: 1,
name: "Sander Cokart",
runTime: [
186
]
}]
}],
hidden: false
}, ]
}
And I wish to filter based on runTimes.start & end,
I have already tried this:
const filtered = array.filter((project) => {
if (!project.hidden) {
if (project.runTimes.filter((runTime) => {
if (moment(runTime.start).isSameOrAfter(context.searchFrom) &&
moment(runTime.end).isSameOrBefore(context.searchTo)) {
return runTime;
}
}).length > 0) {
return project;
}
}
});
sadly it doesn't work the second a second RunTime exists inside a project object RunTimes array.
anyone have an idea?
The filter functions are just a bit off. I'd argue the if statement wrapped around the filter is confusing, I'd go for something simpler. This is working for me:
const result = array.projects.filter((project) => {
return !project.hidden && project.runTimes.filter(runTime => {
return moment(runTime.start).isSameOrAfter("2020-W01") &&
moment(runTime.end).isSameOrBefore("2020-W12")
})
});

Display highcharts graph with a lot of data in angularjs

I have an angularjs application and I use highcharts-ng to display some graphs. I got the data from an http request and I modify the data to display them in the graph.
If I receive just a just some data, it's ok, it works but when I receive a lot of data, the highcharts component take a long time to display the data. And in this time the browser in freezed.
In my controller, I have:
widgetCtrl.chartDataLine = {
chart: {
type: 'spline',
zoomType: 'xy'
},
title: {
text: 'Power Consumption'
},
xAxis: {
type: 'datetime',
title: {
text: 'Date time'
}
},
yAxis: {
title: {
text: 'Power (W)'
},
min: 0
},
options: {
exporting: {
enabled: true,
allowHTML: true,
buttons: {
contextButton: {
menuItems: null,
onclick: function () {
this.exportChart();
}
}
}
}
},
plotOptions:{
series:{
turboThreshold:60000 // larger threshold or set to 0 to disable
}
},
series: []
};
I call the data like that:
var getMetrics = function (searchText) {
var param = {
target: searchText
};
xcsDatasource.get('beo').callAction('getPowerMetrics', param.target, widgetCtrl.pickerFrom.date, widgetCtrl.pickerTo.date).then(
function (result) {
widgetCtrl.metrics = result;
widgetCtrl.metricsAsString = JSON.stringify(result);
var t = getChartData(result);
widgetCtrl.chartDataLine.series = angular.copy(t);
console.log(widgetCtrl.chartDataLine);
//widgetCtrl.chartDataArea.series = getChartData(result);
},
function () {
widgetCtrl.metrics = {};
widgetCtrl.metricsAsString = '';
}
);
};
And this is my html:
<div ng-if="config.linechart" class="graph-container col-sm-12">
<highchart id="chart1" config="pwrDashboardViewCtrl.chartDataLine"></highchart>
</div>
Do you have an idea how I can do to continue to load the grapph without freezing the browser ?

How to share code in angular js (concept of code resuability in angular js?

i am new to angular js and i want to share and make certain codes reusable. i have tried to do that using services and factory. But i am getting error.
'use strict';
angular.module('myApp.ctrls')
.controller('Ctrl_HubStockOnHandMode', function($http, $scope, reportService) {
$scope.HubStockOnHandModeGridOptions = {
dataSource: {
type: "jsonp",
transport: {
read: function(e) {
reportService.WebAPI('abc/BIUMo', {
EnvironmentCode:'JMVH',
OrderBy: getOrderBy(e.data.sort)
}).then(function (d) {
$scope.data = d;
e.success(d.Data);
});
}
},
serverPaging: true,
serverSorting: true
},
height:config.GridHeight,
scrollable:true,
sortable: {
mode: "single",
allowUnsort: true
},
filterable: {
extra: false,
operators: {
string: {
startswith: "Starts with",
eq: "Is equal to",
neq: "Is not equal to",
contains: "Contains"
}
}
},
pageable: false,
columns: [
{
field: "RowNumber"
,title: "No."
,width: "50px"
,sortable:false
,filterable: false
},
{
field: 'ItemCTSH'
,title:'Item'
,template: "<div kendo-tooltip title='#= ItemCT #' > #= ItemCTSH # </div>"
,filterable: {
ui: itemFilter
}
},
]
};
}
//Get Item List
$http.get('http://webapi.dashboard.hcmisonline.org/api/OID_WebApi/IssuedItemList')
.success(function (data) {
$scope.items = data.Data;
});
function itemFilter(element) {
element.kendoAutoComplete({
dataSource: $scope.items
});
}
}
});
I want to reuse the functions like the Get item. i have other pages/grids that use exactly this code, except changing the environment code
how to i solve this issue?
thanks

How to bind template to object in array by property value?

I'm probably looking for a directive of some sort, right?
//JS
$rootScope.cats = [
{ sort:0, value:'ABY', label:'Abyssinian' },
{ sort:1, value:'RGD', label:'Ragdoll' },
{ sort:2, value:'RBL', label:'Russian Blue' },
{ sort:3, value:'OCT', label:'Ocicat' }
];
//HTML
{{cats['ABY'].label}} //This obviously doesn't work. Is there something in Angular that would?
Try to find the proper object in controller, for example:
$scope.cats = [
{ sort: 0, value: 'ABY', label: 'Abyssinian' },
{ sort: 1, value: 'RGD', label: 'Ragdoll' },
{ sort: 2, value: 'RBL', label: 'Russian Blue' },
{ sort: 3, value: 'OCT', label: 'Ocicat' }
];
$scope.selectedCat = _.find($scope.cats, function (cat) {
return cat.value == 'OCT';
});
And put this into your layout:
{{selectedCat.label}}
NB Lodash library is used to find the proper cat.
This can be a candidate for a custom filter. See DEMO
app.filter('label', function(){
return function(arr, value) {
var cats;
if(arr) {
cats = arr.filter(function(elem) {
return elem.value == value;
});
}
return cats && cats.length > 0 ?
cats[0].label : 'Not Found';
}
});

angularjs watch for change in multidimensional array

i have these array object
$scope.alterations = {
'collar' : { name: 'collar', selected: false, qualitative: 'Perfect' },
'chest' : { name: 'chest', selected: false, qualitative: 'Perfect' },
'shoulder' : { name: 'shoulder', selected: false, qualitative: 'Perfect' },
'waist' : { name: 'waist', selected: false, qualitative: 'Perfect' },
'hips' : { name: 'hips', selected: false, qualitative: 'Perfect' },
'sleeve' : { name: 'sleeve', selected: false, qualitative: 'Perfect' },
'biceps' : { name: 'biceps', selected: false, qualitative: 'Perfect' },
'wrist' : { name: 'wrist', selected: false, qualitative: 'Perfect' },
'length' : { name: 'length', selected: false, qualitative: 'Perfect' },
};
// watch alterations for changes
$scope.$watch('alterations|filter:{selected:true}', function (nv) {
$scope.alter = nv.map(function (alterations) {
return alterations;
}); }, true);
what do i need to change in my filter if i want to only get areas with selected:true in the array?
i got these error for the map method
TypeError: Object #<Object> has no method 'map'
update :
before this its working with these array structure :
$scope.alterations = [
{ name: 'collar', selected: false, qualitative: 'Perfect' },
{ name: 'chest', selected: false, qualitative: 'Perfect' },
{ name: 'shoulder', selected: false, qualitative: 'Perfect' },
{ name: 'waist', selected: false, qualitative: 'Perfect' },
{ name: 'hips', selected: false, qualitative: 'Perfect' },
{ name: 'sleeve length', selected: false, qualitative: 'Perfect' },
{ name: 'biceps', selected: false, qualitative: 'Perfect' },
{ name: 'wrist', selected: false, qualitative: 'Perfect' },
{ name: 'shirt length', selected: false, qualitative: 'Perfect' }
];
Give this js fiddle a try, it's using your new data structure. http://jsfiddle.net/8mXD7/ I've included the change below. See the jsfiddle for the full code.
// watch alterations for changes
$scope.$watch('alterations|filter:{selected:true}', function (nv, ov, scope) {
$scope.alter = [];
angular.forEach(nv, function (value, key) {
if (value.selected == true) {
this.push(value);
}
}, $scope.alter);
}, true);
I got rid of the map, and replaced it with a angular.forEach. This also means you don't need the reference to the full jquery library, and you can just use the built in jqlite.
UPDATED WITH ALTERNATE
Here is an alternate approach with a custom filter function. Notice you need to register the filter with the moddule and update your ng-app to point to the new module.
http://jsfiddle.net/TpM4T/ - see the jsfiddle for the full source, this code is different than the code used above.
angular.module('example', []).
filter('customFilter', function () {
return function (arr) {
var alter = [];
angular.forEach(arr, function (value, key) {
if (value.selected == true) {
this.push(value);
}
}, alter);
return alter;
}
});
UPDATED WITH ANOTHER ALTERNATE
This approach uses the filter service, and actually prevents one of the NAIVE array copies.
http://jsfiddle.net/Qxew8/ - this example demonstrates just a regular function that could be used as a function or a filter.
angular.module('example', []).
filter('customFilter', function () {
return makeArrayOfSelected
});
function makeArrayOfSelected(arr) {
var alter = [];
angular.forEach(arr, function (value, key) {
if (value.selected == true) {
this.push(value);
}
}, alter);
return alter;
};
So in the watch it just calls the filter service:
// watch alterations for changes
$scope.$watch('alterations', function (nv, ov, scope) {
$scope.alter = $filter("customFilter")(nv);
}, true);

Resources