ng-repeat in ChartJS AngularJS - arrays

I have the following difficulty.
At the time of displaying the data with ng-repeat it does not show me any results.
you can see my code in CodePen
<link rel="stylesheet" href="http://jtblin.github.io/angular-chart.js/node_modules/bootstrap/dist/css/bootstrap.min.css">
<script src="http://jtblin.github.io/angular-chart.js/node_modules/angular/angular.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/node_modules/chart.js/dist/Chart.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/dist/angular-chart.js"></script>
<script>
var app = angular.module("RodoApp", ["chart.js"]);
app.controller("ChartController", function ($scope, $http) {
$scope.person = [
{
"name": "Rodrigo",
"number": 5,
},
{
"name": "Carlos",
"number": 11,
},
{
"name": "Arnold",
"number": 20,
}
];
$scope.labels = [];
$scope.data = [];
for (i = 0; i < $scope.person.length; i++) {
$scope.labels.push($scope.person[i].name);
$scope.data.push($scope.person[i].number);
}
$scope.options = {
legend: {
display: true,
},
title: {
display: true,
text: 'title'
} };
});
</script>
<body ng-app="RodoApp" ng-controller="ChartController">
<div ng-repeat="t in person">
<div>{{t.name}} - {{t.number}}</div>
</div>
<hr />
<div ng-repeat="options in person">
<canvas id="{{options.name}}" class="chart chart-pie" chart-options="options" chart-data="options.data" chart-labels="options.labels" />
</div>
</body>
EXAMPLE
RESULT
I need to count the IdSurveyQuestionAnswer to assign to their respective IdSurveyQuestion

There's a few issues with the code that you've posted. The key ones that I see that will get the chart rendering happening are as follows:
First, your ng-repeat is using options, but you also have a scope variable called options, and I think they are clashing (or at the very least, not doing what you think they are doing).
Changing $scope.options = {...} to $scope.chartOptions = {...}, and chart-options="options" to chart-options="chartOptions" will fix this.
Second, your ng-repeat is looking for chart-data and chart-labels inside each person. You've only defined name and number, so there is no data to display.
On this, I can see that you've iterated over the person array and dropped all the information into a scope data and labels array.
That means that while you are rendering a chart per person, you're effectively rendering the same chart each time.
A full working version follows:
<link rel="stylesheet" href="http://jtblin.github.io/angular-chart.js/node_modules/bootstrap/dist/css/bootstrap.min.css">
<script src="http://jtblin.github.io/angular-chart.js/node_modules/angular/angular.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/node_modules/chart.js/dist/Chart.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/dist/angular-chart.js"></script>
<script>
var app = angular.module("RodoApp", ["chart.js"]);
app.controller("ChartController", function ($scope, $http) {
$scope.person = [
{
"name": "Rodrigo",
"number": 5,
},
{
"name": "Carlos",
"number": 11,
},
{
"name": "Arnold",
"number": 20,
}
];
$scope.labels = [];
$scope.data = [];
for (i = 0; i < $scope.person.length; i++) {
$scope.labels.push($scope.person[i].name);
$scope.data.push($scope.person[i].number);
}
$scope.chartOptions = {
legend: {
display: true,
},
title: {
display: true,
text: 'title'
}
};
});
</script>
<body ng-app="RodoApp" ng-controller="ChartController">
<div ng-repeat="t in person">
<div>{{t.name}} - {{t.number}}</div>
</div>
<hr />
<div ng-repeat="options in person track by $index">
<canvas ng-attr-id="{{options.name}}" class="chart chart-pie" chart-options="chartOptions" chart-data="data" chart-labels="labels" />
</div>
</body>
While this renders the charts, the make up of the data and why you want to repeat this is something that you'll need to think about, and possible ask another question on.

Related

How can I apply ng-style dynamically if ng-class is true?

.test{color:red;background:blue;}
.test.selected {
position:relative; left: 100px; padding:10px; background:green;
}
<div ng-style="myStyle" ng-class="{select: x.selected}" ng-click="select(x)" ng-repeat="x in myData" class="test"></div>
$scope.select = function (text) {
text.selected = true;
};
$scope.myStyle = {
'color':'white',
'font-weight':'bold'
}
When the div element has className "selected" by using condition true, how can I add 'myStyle' in ng-style as well. How to apply inline ng-style dynamically if ng-class condition is true? Here below I am able to see in debugger in inline with classNames added. Now I have the condition true and I can see the classname "selected" to it(class="test ng-scope selected"), All I want is an inline ng-style="myStyle" to be added when its true.
<div ng-class="{select: x.selected}" ng-click="select(x)" class="test ng-scope selected" ng-repeat="x in myData">
Try like to this.
<div ng-style="x.selected && {'color':'white','font-weight':'bold'}"
ng-click="select(x)" ng-repeat="x in myData" ></div>
Demo
var app = angular.module('anApp', ['angular.filter']);
app.controller('aCtrl', function($scope) {
$scope.data = [
{
"id": 100,
"value": "2452"
},
{
"id": 100,
"value": "2458"
},
{
"id": 1,
"value": "2457"
},
{
"id": 1,
"value": "2459"
},
{
"id": 4,
"value": "2460"
},
{
"id": 5,
"value": "3458"
}
];
$scope.select = function(x){
x.selected = !x.selected;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>
<div ng-app="anApp" ng-controller="aCtrl">
<div ng-style="x.selected && {'color':'red','font-weight':'bold'}"
ng-click="select(x)" ng-repeat="x in data" >
{{x.value}}
</div>
</div>
Dont use ng-style for selected item, you can do this with ng-class(Recommended)
Style
.selected {
'color':'white',
'font-weight':'bold'
}
HTML
<div ng-class="{'selected': x.selected}" ng-click="select(x)" ng-repeat="x in myData" ></div>
Controller
$scope.select = function(x){
x.selected = !x.selected;
}

ng-repeat filter by one key and two value

This is my JSON data:
[
{
"name": "elin",
"family": "kinoian"
},
{
"name": "simon",
"family": "santos"
},
{
"name": "sara",
"family": "pinki"
},
{
"name": "emin",
"family": "richard"
}
]
As you can see,I have 2 key in each row "name" and "family.
This is my ng-repeat filtering by json object "search":
<li ng-repeat="membr in familyMember| filter:search">
<span> {{membr.name}} - {{membr.family}}</span>
</li>
And these are my inputs for filtering:
By name: <input type="text" ng-model="search.name1">
and <input type="text" ng-model="search.name2">
By family: <input type="text" ng-model="search.family">
I need the rows which name is "elin" and "sara". I`m looking for "AND Condition" in filtering. How can I do that?
First of all, no, you're not looking for an AND condition, but for an OR. Indeed, a family member can't be named "elin" and "sara" at the same time.
Now, if you read the documentation for the filter filter, you'll see that it accepts a function as argument, which must return a truthy value if the value is accepted, and a truthy value if it's rejected. So all you need is
ng-repeat="member in familyMember| filter:isAccepted">
and
$scope.isAccepted = function(member) {
return member.name === $scope.search.name1 || member.name === $scope.search.name2;
}
You need to use a custom filter with OR condition.
$scope.nameFilter = function(member) {
var result = (member.name == $scope.membr.name1) ||
(member.name == $scope.membr.name2) ||
(member.family == $scope.membr.family);
return result;
};
DEMO
var myApp = angular.module('myApp', []);
myApp.controller("MyCtrl", ['$scope', function($scope) {
$scope.familyMember = [{
"name": "elin",
"family": "kinoian"
}, {
"name": "simon",
"family": "santos"
}, {
"name": "sara",
"family": "pinki"
}, {
"name": "emin",
"family": "richard"
}];
$scope.nameFilter = function(member) {
var result = (member.name == $scope.membr.name1) ||
(member.name == $scope.membr.name2) ||
(member.family == $scope.membr.family);
return result;
};
}]);
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://code.angularjs.org/1.4.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="MyCtrl">
By name:
<input type="text" ng-model="membr.name1" > and
<input type="text" ng-model="membr.name2"> By family:
<input type="text" ng-model="membr.family">
<li ng-repeat="membr in familyMember| filter:nameFilter">
<span> {{membr.name}} - {{membr.family}}</span>
</li>
</div>
</body>
</html>
Try this working demo :
var app = angular.module('myApp',[]);
app.controller('mainCtrl', function($scope) {
$scope.familyMember = [
{
"name": "elin",
"family": "kinoian"
},
{
"name": "simon",
"family": "santos"
},
{
"name": "sara",
"family": "pinki"
},
{
"name": "emin",
"family": "richard"
}
];
$scope.search = function(membr) {
return membr.name === $scope.search.name1 || membr.name === $scope.search.name2;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp' ng-controller='mainCtrl'>
name1: <input type="text" ng-model="search.name1">
name2: <input type="text" ng-model="search.name2"><br><br>
<li ng-repeat="membr in familyMember | filter:search">
<span> {{membr.name}} - {{membr.family}}</span>
</li>
</div>

AngularJS : `Load more` button in each group of ng-repeat with many groups titles

I want to add load more button to the bottom of each group like the image here, and after clicking the button it shows rest of parts of the relevant group
where a,g are groups titles those have group property
In the snippet bellow, the code return only one load more button, and with no consideration of the group property.
var myApp = angular.module('myApp',[]);
myApp.controller('main', ['$scope', function($scope) {
$scope.test = "test";
$scope.filteredModules = [
{
"name":"a",
"group":"a"
},
{
"name":"b",
},
{
"name":"c",
},
{
"name":"c",
},
{
"name":"e",
},
{
"name":"f",
},
{
"name":"g",
"group":"g"
}
,{
"name":"h",
},
{
"name":"i",
},
{
"name":"j",
},
{
"name":"k",
}
,
{
"name":"l",
}
];
$scope.limit = 4;
$scope.loadMore = function() {
var increamented = $scope.limit + 4;
$scope.limit = increamented > $scope.filteredModules.length ? $scope.filteredModules.length : increamented;
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="main">
<div ng-repeat="node in filteredModules | limitTo:limit track by $index">
<div ng-if="!node.group">{{node.name}}</div>
<div ng-if="node.group" style="background-color:red">{{node.name}} </div>
</div>
<button ng-click="loadMore()">Load more</button>
</div>
</div>
Please try this snippet
var myApp = angular.module('myApp',[]);
myApp.controller('main', ['$scope', function($scope) {
$scope.filteredModules = {
"groups":
[
{
"title": "Alfreds Futterkiste",
"childs": ["child-1", "child-2", "child-3", "child-4", "child-5", "child-6","child-7", "child-8", "child-9"],
"limit": "3"
},
{
"title": "Ana Trujillo Emparedados y helados",
"childs": ["child-1", "child-2", "child-3", "child-4", "child-5", "child-6"],
"limit": "4"
},
{
"title": "Antonio Moreno Taquería",
"childs": ["child-1", "child-2", "child-3", "child-4", "child-5", "child-6"],
"limit": "3"
}
]
};
$scope.loadMore = function(index) {
$scope.filteredModules.groups[index].limit = parseInt($scope.filteredModules.groups[index].limit) + 3;
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="main">
<div ng-repeat="node in filteredModules.groups track by $index">
<div ng-if="node.title" style="background-color:red">{{node.title}}
</div>
<div ng-repeat="child in node.childs | limitTo: node.limit">
{{child}}
</div>
<br/>
<button ng-click="loadMore($index)" ng-hide="node.limit >= node.childs.length">Load more</button>
<br/><br/>
</div>
</div>
</div>

Directives inside ng-repeat to create a new structure with AngularJS

I'm trying to create a new array from an exiting array of parameters with AngularJS.
Explaining better:
I have an array of parameters:
"parameters": [
{"id":2,"exibitionName":"gaps","name":"--gaps","description":"Nº de GAPS permitido","defaultValue":null},
{"id":4,"exibitionName":"Block Size","name":"--block-size","description":"Tamanho dos blocos","defaultValue":null}
]
With this array I create with ng-repeat a set of inputs to take the respective value of each parameter from the user:
<div class='row well well-sm' ng-show='selectedAlg'>
<div class='col-md-3' ng-repeat='parameter in selectedAlg.parameters'>
<label class="control-label">{{parameter.exibitionName}}</label>
<input class="form-control input-sm" type="text">
</div>
</div>
In the end I want to have another array of parameters with this structure:
"parameters": [
{paramName:"--threads", paramValue:"18"},
{paramName:"--gaps", paramValue:"2"}
]
What directives I need to use in the input to take the value and build this new structure I want?
I tried you requirement with ng-change directive in the input tag and kept one button to generate your end array when you click that button.
Take a look at the code,
<html ng-app="myApp">
<head>
<script data-require="angular.js#1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="myController">
<div ng-show='selectedAlg'>
<div ng-repeat="parameter in selectedAlg.parameters">
<label>{{parameter.exibitionName}}</label>
<input id="{{$index}}" ng-model="val" type="text" ng-change="insertArray = $index==selectedAlg.parameters.length-1?true:false;
setParamvalues(val, insertArray)"></input>
</div>
<button type="button" ng-click="constructArray();">Construct Array</button>{{endArray}}
</div>
</body>
</html>
Here is the controller,
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.endArray = [];
$scope.selectedAlg = {
"parameters": [
{
"id": 2,
"exibitionName": "gaps",
"name": "--gaps",
"description": "Nº de GAPS permitido",
"defaultValue": null
},
{
"id": 4,
"exibitionName": "Block Size",
"name": "--block-size",
"description": "Tamanho dos blocos",
"defaultValue": null
}
]
};
$scope.setParamvalues = function(values, insertArray) {
if(!insertArray) {
$scope.paramName = values;
}
if(insertArray) {
$scope.paramValue = values;
}
}
$scope.constructArray = function() {
$scope.endArray.push({
paramName: $scope.paramName,
paramValue: $scope.paramValue
});
}
});
Working plunker
Hope this helps!

How do I cancel drag between different lists when using angular-ui's sortable module

I am using angular-ui's sortable-ui module and am trying to raise a cancel so that the dragged items returns to it original location in the source list. Unfortunately I cannot get this working. Here is an example:
http://jsfiddle.net/Ej99f/1/
var myapp = angular.module('myapp', ['ui.sortable']);
myapp.controller('controller', function ($scope) {
$scope.list = ["1", "2", "3", "4", "5", "6"];
$scope.list2 = ["7", "8", "9"];
$scope.sortableOptions = {
update: function(e, ui) {
if (Number(ui.item.text()) === 6) {
ui.item.parent().sortable('cancel');
}
},
receive: function(e, ui) {
ui.sender.sortable('cancel');
ui.item.parent().sortable('cancel');
},
connectWith: ".group",
axis: 'y'
};
});
angular.bootstrap(document, ['myapp']);
Any help would be gratefully appreciated.
well, when it comes to angular, all roads lead to the data "the single source of truth". So update your model back to it's original state, before the move, and you're all set :)
example below has two lists, the first one being restricted for
its sorting (the update method)
and for sending an item (receive method on list 2)
the second list you can sort, and send items to list 1
(using foundation4 for css)
<div ng-app="test">
<div ng-controller="sortableTest">
<div class="small-4 columns panel">
<ul data-drop="true"
ui-sortable="sortable.options.list1" ng-model="sortable.model.list1">
<li ng-repeat="fruit in sortable.model.list1"
data-id="{{ fruit.id }}">{{ fruit.label }}</li>
</ul>
</div>
<div class="small-4 columns panel">
<ul data-drop="true"
ui-sortable="sortable.options.list2" ng-model="sortable.model.list2">
<li ng-repeat="element in sortable.model.list2"
data-id="{{ element.id }}">{{ element.label }}</li>
</ul>
</div>
<div class="clear"></div>
<br />
<span ng-repeat="fruit in sortable.model.list1">{{ fruit.label }} </span><br />
<span ng-repeat="element in sortable.model.list2">{{ element.label }} </span><br />
<span ng-repeat="fruit in sortable.oldData.list1">{{ fruit.label }} </span><br />
<span ng-repeat="element in sortable.oldData.list2">{{ element.label }} </span><br />
</div>
</div>
js:
var test = angular.module('test', ['ui.sortable']);
test.controller('sortableTest', function($scope, $timeout) {
$scope.sortable = {
model: {
list1: [{id: 1, label: 'apple'},{id: 2, label: 'orange'},{id: 3, label: 'pear'},{id: 4, label: 'banana'}],
list2: [{id: 5, label: 'earth'},{id: 6, label: 'wind'},{id: 7, label: 'fire'},{id: 8, label: 'water'}]
},
oldData: {
list1: [],
list2: []
},
options: {
list1: {
update: function(event, ui) {
console.debug('up-list1');
$scope.sortable.oldData.list1 = $scope.sortable.model.list1.slice(0);
$scope.sortable.oldData.list2 = $scope.sortable.model.list2.slice(0);
// DO NOT USE THIS! it messes up the data.
// ui.item.parent().sortable('cancel'); // <--- BUGGY!
// uncomment and check the span repeats..
$timeout(function(){
$scope.sortable.model.list1 = $scope.sortable.oldData.list1;
$scope.sortable.model.list2 = $scope.sortable.oldData.list2;
});
},
connectWith: 'ul'
},
list2: {
update: function(event, ui) {
console.debug('up-list2');
},
connectWith: 'ul',
receive: function(event, ui) {
console.debug('re-list2');
$timeout(function(){
$scope.sortable.model.list1 = $scope.sortable.oldData.list1;
$scope.sortable.model.list2 = $scope.sortable.oldData.list2;
});
}
}
}
};
});
you can of course use a service or something to store the old value. One can use ui.sender to differentiate the senders, if you have more that two..

Resources