Use scope variable in ng-repeat - angularjs

I want to use a $scope variable within the ng-repeat attribut, like so :
<div class="userOpinion" ng-if="usersOpinions.length != 0" ng-repeat="userOpinion in {{usersOpinion}}">
But it doesnt seem to work, {{usersOpinion}} remains non-interpreted... How could I manage to make it work?
The Idea is to dynamically change {{usersOpinion}} when clicking on button.
Thanks

Instead of ng-repeat="userOpinion in {{usersOpinion}}" ,change it to ng-repeat="userOpinion in usersOpinions.
You should use like
<div class="userOpinion" ng-if="usersOpinions.length != 0" ng-repeat="userOpinion in usersOpinions">{{userOpinion}}</div>

It should be enough to remove the curly brackets. The ng-repeat is interpreted as code.
<div class="userOpinion" ng-if="usersOpinions.length != 0" ng-repeat="userOpinion in usersOpinion">
The curly brackets tells angular that it should transform the variable into a string before outputting it.

If you want to change it dynamically you need to add ng-click to div tag, something like this
<div class="userOpinion" ng-if="usersOpinions.length != 0" ng-repeat="userOpinion in usersOpinion" ng-click="changeOpinion($index)">
{{userOpinion}}
</div>
and add function to scope
$scope.changeOpinion = function (index) {
$scope.usersOpinion[index] += '1';
}
no you can do whaterver you want with value of that opinion, here is the whole code with both simple array of opinions and objects http://jsfiddle.net/Lvc0u55v/9513/

if I'm understand your question, you can try this
var autoDrops = angular.module('autoDrops', []);
autoDrops.controller('DropsController', function($scope) {
$scope.usersOpinion = [];
$scope.datas = [{
"name": "item01"
}, {
"name": "item02"
}, {
"name": "item03"
}, {
"name": "item04"
}, {
"name": "item05"
}, {
"name": "item06"
}];
$scope.datas1 = [{
"name": "item11"
}, {
"name": "item12"
}, {
"name": "item13"
}, {
"name": "item14"
}, {
"name": "item15"
}, {
"name": "item16"
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="autoDrops" ng-controller="DropsController">
<button ng-click="usersOpinion = datas">
data
</button>
<button ng-click="usersOpinion = datas1">
datas1
</button>
<div>
<div ng-repeat="elem in usersOpinion">
{{elem}}
</div>
</div>
</div>

Related

Comparing objects from two scopes to provide a value

I'll try to simplify the problem as much as I can.
Let's say I have 2 scopes
$scope.section1 = [
{label: 'label1'},
{label: 'label2'}
];
$scope.section2 = [
{value: 'one'},
{value: 'two}
];
Those scopes are used to generate buttons with ng-repeat
<button ng-repeat="item in section1 type="button">{{item.label}}</button>
and
<button ng-repeat="item in section2 type="button">{{item.value}}</button>
Now what I would like to do it to create a third scope that would attach values to the combinations of objects from the two previous ones, say:
$scope.combo = [
{ section1.label:label1 + section2.value: one = 'result1' },
{ section1.label:label2 + section2.value: one = 'result2' },
{ section1.label:label1 + section2.value: two = 'result3' },
{ section1.label:label2 + section2.value: two = 'result4' }
];
Now here comes the tricky part. What I would need to do, is to add a function that would take the values of clicked ng-repeat buttons from each section and then display the results based on the third scope in an input field or something.
So, if you click the button with label:label1 and the one with value:two the input field would show result3.
I'm very green when it comes to Angular and I have no idea how to approach it, especially that all values are strings.
If I understand correctly you could setup your combo something like ...
$scope.combo = {
"label1": {
"one": "result1",
"two": "result2"
},
"label2": {
"one": "result3",
"two": "result4"
}
}
You can then reference the correct value as combo[valueFromButton1][valueFromButton2] where valueFromButton1 and valueFromButton2 point at a model that contains the result of the clicked buttons. Your controller function then just needs to tie everything together by updating the model when the buttons are clicked.
See this plunkr ... https://embed.plnkr.co/GgorcM/
Without changing much you can also try like below provided code snippet.Run it to check the demo.
var app = angular.module('app', []);
app.controller('Ctrl',['$scope' ,function($scope) {
var key1, key2;
$scope.click = function(type, item) {
if (type == 'label') {
key1 = item;
} else if (type == 'val') {
key2 = item;
}
$scope.key = key1 + '+' + key2;
angular.forEach($scope.combo, function(val, key) {
if(val[$scope.key]){
$scope.finalVal = val[$scope.key];
}
});
};
$scope.section1 = [{
label: 'label1'
}, {
label: 'label2'
}];
$scope.section2 = [{
value: 'one'
}, {
value: 'two'
}];
$scope.combo = [{
'label1+one': 'result1'
}, {
'label2+one': 'result2'
}, {
'label1+two': 'result3'
}, {
'label2+two': 'result4'
}];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='Ctrl'>
<button ng-repeat="item in section1" ng-click="click('label',item.label)" type="button">{{item.label}}</button>
<button ng-repeat="item in section2" ng-click="click('val',item.value)"type="button">{{item.value}}</button>
<input type="text" ng-model="finalVal"/>{{key}} {{finalVal}}
</div>

Angular2 removing duplicates from an JSON array

I have a problem with filter in my JSON array when I move my app to Angular2 . In Angular 1.x that was easier. I used 'unique' in filter and this remove all duplicates.
apps:
{"app":"database_1",
"host":"my_host1",
"ip":"00.000.00.000"
},
{"app":"database_1",
"host":"my_host1",
"ip":"00.000.00.000"
},
{"app":"database_2",
"host":"my_host2",
"ip":"00.000.00.000"
},
{"app":"database_2",
"host":"my_host2",
"ip":"00.000.00.000"
}
Part of html code:
<div *ngFor='#appsUnique of apps '>
<div class="row dashboard-row">
<div class="col-md-2">
<h4>{{appsUnique.app }}</h4>
</div>
</div>
</div>
And result is:
database_1
database_1
database_2
database_2
I want to get result:
database_1
database_2
How can I remove duplicates from an array?
Mybe it can help you
myList = ["One","two","One","tree"];
myNewList = Array.from(new Set(myList ));
I have a solution for this problem :)
Array.from(new Set([{"app":"database_1",
"host":"my_host1",
"ip":"00.000.00.000"
},
{"app":"database_1",
"host":"my_host1",
"ip":"00.000.00.000"
},
{"app":"database_2",
"host":"my_host2",
"ip":"00.000.00.000"
},
{"app":"database_2",
"host":"my_host2",
"ip":"00.000.00.000"
}].map((itemInArray) => itemInArray.app)))
More about Array.from & Set
Thanks all for help :)
You could use following method:
names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
ngOnInit() {
let filteredNames=this.remove_duplicates(this.names);
console.log(filteredNames);
console.log(this.names);
}
remove_duplicates(arr) {
let obj = {};
for (let i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
arr = [];
for (let key in obj) {
arr.push(key);
}
return arr;
}
Hope this helps.
You could use Observable approach as well, It is very simple.
let filteredData = [];
let arrayData = [{
"app": "database_1",
"host": "my_host1",
"ip": "00.000.00.000"
},
{
"app": "database_1",
"host": "my_host1",
"ip": "00.000.00.000"
},
{
"app": "database_2",
"host": "my_host2",
"ip": "00.000.00.000"
},
{
"app": "database_2",
"host": "my_host2",
"ip": "00.000.00.000"
}];
Observable.merge(arrayData)
.distinct((x) => x.app)
.subscribe(y => {
filteredData.push(y)
console.log(filteredData)
});
instead of looping over the normal json array, you can create another array in your corresponding typescript class, and alter this as you see fit. In your html, you can then have the following
html
<div *ngFor='let appsUnique of filteredApps'>
<div class="row dashboard-row">
<div class="col-md-2">
<h4>{{appsUnique.app }}</h4>
</div>
</div>
</div>
Next, you need this filteredApps array in your corresponding typescript class.
typescript
let filteredApps = [];
and in a function you can then create that filteredApps, for example in the onInit method.
onInit()
{
filteredApps = // filter logic
}
You will need trackBy.
Try with:
*ngFor="#appsUnique of posts;trackBy:appsUnique?.app"
Hope it helps.

How to apply dynamic filters in AngularJS

I'm starting to learn AngularJS now and I have some issues with filters.
I need to apply two types of filters and I can't figure out how.
I have a device list JSON that looks like this:
[{
"ID": 1,
"Name": "Device 1",
"Price": 1998.92,
"Colors": [{
"ColorCode": "Red",
"ColorName": "#FF0000"
},
{
"ColorCode": "Green",
"ColorName": "#2EFE2E"
}],
"Type": {
"TypeID": 1,
"TypeName": "Mobile device"
},
"Company": {
"CompanyID": 1,
"CompanyName": "Alcatel"
}
}]
I display the list like this:
<div ng-repeat="device in devices | filter:companyFilters | filter:colorFilters">
<span>{{device.Company.CompanyID}}</span> // 1
<span>{{device.Company.CompanyName}}</span> // Google
<span>{{device.Name}}</span> // Nexus 6P
</div>
I have some filters that I applied but there are two filters that I can't understand how to apply.
Filter 1:
A checkbox list of companies that filters the items by the selected
companies.
Filter 2:
A color filter that when clicking on a color will filter the devices
that has that color
For the company filter I have this checkbox list:
<div ng-repeat="company in deviceCompanies">
<input type="checkbox" data-ng-model="companyFilters" id="{{company.CompanyID}}" data-ng-true-value='{{company.CompanyID}}' data-ng-false-value='' />
<label for="{{company.CompanyID}}">{{company.CompanyName}}</label>
</div>
And on the controller side I have this:
$scope.companyFilters = [];
For the color filter I have this:
<div>
<a ng-click="???">All</a>
<div ng-repeat="color in deviceColors" style="display:inline-block; margin-right:10px;">
<div style="width:20px;height:20px;background-color:{{color.ColorCode}}"></div>
<a ng-model="selColor" data-ng="color.ColorCode" ng-click="colorFilters">{{color.ColorName}}</a>
</div>
</div>
And on the controller:
$scope.colorFilters = function (device) {
if (!$scope.selColor)
return true;
for (var i = 0; i < device.Colors.length; i++) {
if (device.Colors[i].ColorCode == $scope.selColor)
return true;
}
return false;
};
But it doesn't work...
Can anyone please tell me how to apply these filters ?
Since you are using ng-repeat which creates its own scope, anything you do in ng-repeat will not get recognized on the controller scope. Using a tool like ng-inspector or batarang will illustrate this.
I recommend using controllerAs Syntax, in your controller add.
angular.module('myModule').controller('CustomFilterController', function() {
var vm = this;
this.devices = //your list of data
this.companyFilters = [];
this.colorFilters = //your function
}
On your view declare your controller like this:
<div ng-controller='CustomFilterController as custom'>
(Note the value after as can be whatever you want it to be)
Then reference anything on that controller as custom.ThingOnController
EX:
<div ng-repeat="device in custom.devices | filter:custom.companyFilters | filter:custom.colorFilters">
After trying some workarounds, this is what I came up with:
<div ng-repeat="company in deviceCompanies">
<!--the ng-click will call a function that updated an array of values-->
<input type="checkbox" id="{{company.CompanyID}}" ng-click="selectCompany(company.CompanyID)">
<label for="{{company.CompanyID}}">{{company.CompanyName}}</label>
</div>
And the controller part is so simple:
$scope.selectedCompanies = [];
//when the array is upted the filter function will also launch
$scope.selectCompany = function (companyId) {
var i = $.inArray(companyId, $scope.selectedCompanies);
if (i > -1) {
$scope.selectedCompanies.splice(i, 1);
} else {
$scope.selectedCompanies.push(companyId);
}
}
$scope.companyFilter = function (device) {
if ($scope.selectedCompanies.length > 0) {
if ($.inArray(device.Company.CompanyID, $scope.selectedCompanies) < 0)
return;
}
return device;
}
Same goes to the colors filter:
<div>
<a ng-click="selectColor()">All</a>
<div ng-repeat="color in deviceColors" style="display:inline-block; margin-right:10px;">
<div style="width:20px;height:20px;background-color:{{color.ColorCode}}"></div>
<a ng-click="selectColor(color.ColorCode)">{{color.ColorName}}</a>
</div>
</div>
And controller part:
$scope.selectedColor;
$scope.selectColor = function (colorCode) {
$scope.selectedColor = colorCode;
}
$scope.colorFilters = function (device) {
if (!$scope.selectedColor)
return true;
for (var i = 0; i < device.Colors.length; i++) {
if (device.Colors[i].ColorCode == $scope.selectedColor)
return true;
}
return false;
};
And finally, applying the filters:
<div ng-repeat="device in devices | filter:companyFilter | filter:colorFilters">
...
</div>
You can have a look here to see how it works
I think the color filter can be more elegant, but, for now, this does the trick.
If I'll come up with a better solution I'll post it here.

AngularJs - Changing the value of property

I am new to anuglar Js. I am trying to figure out How do i change the property value.
$scope.dashboards = {
"1": {
"widgets": [{
"row": 0,
"col": 0,
"sizeX": 2,
"sizeY": 1,
"name": "Canvas 1",
"canvas": "canvas_1",
"show": true
}, {
"row": 0,
"col": 2,
"sizeX": 2,
"sizeY": 1,
"name": "Canvas 2",
"canvas": "canvas_2",
"show": true
}]
}
}
On ng-click , i want to change the value of key "show" to false.
<div gridster-item="widget" ng-repeat="widget in dashboard.widgets">
<i ng-click="changeValue(widget)" class="glyphicon glyphicon-trash">
</div>
$scope.changeValue= function (widget) {
.....How to??
};
Since you are already passing the current widget as a parameter, you can do Like this
$scope.changeValue= function (widget) {
widget.show = false;
};
I would not pass the widget. Instead I would pass its $index:
<i ng-click="changeValue($index)" class="glyphicon glyphicon-trash">
And then:
$scope.changeValue= function (index) {
$scope.dashboards.1.widgets[index].show = ...
};
It's look like your array in ng-repeat is undefined in scope.
You should update your codes like below;
<div gridster-item="widget" ng-repeat="widget in dashboards.1.widgets">
<i ng-click="changeValue(widget)" class="glyphicon glyphicon-trash">
</div>
After you get related object and update show property in $scope like below:
$scope.changeValue= function (widget) {
$scope.dashboards.1.widgets[widget].show = false;
};
Simply,
$scope.changevalue= function(widget){
for (var i = 0; i < $scope.dashboards.length; i++) {
for (var j = 0; j < $scope.dashboards[i].widgets.length; j++) {
if ($scope.dashboards[i].widgets[j].ID == widget.ID){
$scope.dashboards[i].widgets[j].show= false
}
};
};
}

ng-table filter with nested properties

I have following JSON:
[{
"Id": "1",
"Data": {"Str1": "Ann", "Str2": "Xenna"}
},{
"Id": "2",
"Data": {"Str1": "Bob","Str2": "Bobby"},
}]
And I created ng-table to display it. I tried to add filter. When I filter by Id everything works as expected (filter is { "Id": "2" }). But I cannot create proper filter do Str1 and Str2 fields. I already tried:
{ "Str1": "A" }
{ "Data.Str1": "A" }
{ "Data['Str1']": "A" }
but above options does not work.
Example of my work is here: http://plnkr.co/edit/MyJCqTlgvKLtSP63FYQY?p=preview
Update
Thanks to #Blackhole I founded that filter {Data: {Str1: 'A'}} works. But I can only delcare this in code. When I try to put something like this in HTML it doesn't even show filter:
<td data-title="'Str1'" filter="{Data:{Str1: 'text'}}">
{{ user.Data.Str1 }}
</td>
When you try to use filter="{Data:{Str1: 'text'}}" in html,input doesn't showing cause of template in header,have a look in source code.
<div ng-repeat="(name, filter) in column.filter"> //!!!! right here it's not supported
<div ng-if="column.filterTemplateURL" ng-show="column.filterTemplateURL">
<div ng-include="column.filterTemplateURL"></div>
</div>
<div ng-if="!column.filterTemplateURL" ng-show="!column.filterTemplateURL">
<div ng-include="'ng-table/filters/' + filter + '.html'"></div>
</div>
</div>
right here <div ng-repeat="(name, filter) in column.filter"> it's not dig into nested objects
Ngtable not support nested filter in default template,so you can create your own template,which gonna support it.Have a look to example of header template.
Note
This how column.filter is initializing,it's parsing from filter attribute on td tag,source
var parsedAttribute = function (attr, defaultValue) {
return function (scope) {
return $parse(el.attr('x-data-' + attr) ||
el.attr('data-' + attr) ||
el.attr(attr))
(scope, {
$columns: columns
}) || defaultValue;
};
};
var parsedTitle = parsedAttribute('title', ' '),
headerTemplateURL = parsedAttribute('header', false),
// here
filter = parsedAttribute('filter', false)(),
filterTemplateURL = false,
filterName = false;
...
columns.push({
....
filter: filter,

Resources