ng-class - finding a value inside object - angularjs

I have an object that looks like this:
$scope.things = [
{
name: 'Bob!',
short_name: 'bob',
info: 'something something'
},
{
name: 'Steve',
short_name: 'steve',
info: 'something something something'
},
];
I loop through them like this and add an ng-click:
<div ng-repeat="thing in things" ng-click="addThing(thing.name, thing.short_name, thing_info" ng-class="thingClass(thing.name)">content goes here</div>
the ng-click="addThing()" basically bunches up the values and adds them to the object.
When clicked, it should add the class selected - this worked fine and dandy when I wasn't using a multidimensional object, because it was simply looking for name inside the object / array (at this point, I think it's an object... but at the time, it was an array)
I can't work out how to do the equivalent to this...
$scope.thingClass= function(name) {
if($scope.thingSelected.indexOf(name) != -1) {
return 'selected';
}
};
...with the object as it now stands. I've tried to adapt a few answers from here that I found through google, such as:
$scope.teamClass = function(name) {
var found = $filter('filter')($scope.thingSelected, {id: name}, true);
if (found.length) {
return 'selected';
}
};
...but with no joy.
Can anyone point / nudge me in the right direction?

You could simply pass the thing object to thingClass:
... ng-class="thingClass(thing)" ...
and implement thingClass as follows:
$scope.thingClass= function(thing) {
return $scope.thingSelected.indexOf(thing) >= 0 ? 'selected' : '';
}
And maybe your should apply this technique to addThing also:
... ng-click="addThing(thing)" ...
$scope.addThing = function(thing) {
if ($scope.thingSelected.indexOf(thing) < 0)
$scope.thingSelected.push(thing);
}
But instead of tracking the selected things in an array its much easier to introduce a selected property in each thing:
$scope.addThing = function(thing) {
thing.selected = true;
}
$scope.thingClass= function(thing) {
return thing.selected ? 'selected' : '';
}

Related

handlebars.js - Select loop based on helper output

In my page I have 2 set of loop in my context.js
set_1: [
{title: 'Set 1'},
{title: 'Set 1'},
{title: 'Set 1'}
],
set_2: [
{title: 'Set 2'},
{title: 'Set 2'},
{title: 'Set 2'}
]
Currently I'm doing:
{{#each set_1}}
{{title}}
{{/each}}
{{#each set_2}}
{{title}}
{{/each}}
What I want to achieve is based on url parameters be able to select which set to show. For instance: domain.com/?set=1 & domain.com/?set=2 and based on this, right set will be set in the loop and shows that.
I tried to create a helper for it as below, but it doesn't give error or show the content:
function getUrlParam(name) {
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
return (results && results[1]) || undefined;
}
var s = getUrlParam('set');
Handlebars.registerHelper('selectSet', function(){
if (s == 1){
return 'set_1'
} else if (s == 2) {
return 'set_2'
} else {
return 'set_1'
}
});
and in my html page, I do:
{{#each selectSet}}
{{title}}
{{/each}}
Any help is appreciated and thanks in advance!
There is no support for such functionality to chain helpers : https://github.com/wycats/handlebars.js/issues/304. If you want such a thing you have to write a helper that will chain the result produced by the first helper to the second (but forget about #each).
In the post you'll find code about writing such a helper :
Handlebars.registerHelper('chain', function () {
var helpers = [], value;
$.each(arguments, function (i, arg) {
if (Handlebars.helpers[arg]) {
helpers.push(Handlebars.helpers[arg]);
} else {
value = arg;
$.each(helpers, function (j, helper) {
value = helper(value, arguments[i + 1]);
});
return false;
}
});
return value;
});
I managed to achieve this with the built-in function lookup that handlebarjs has as follow:
function getUrlParam(name) {
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
return (results && results[1]) || undefined;
}
var s = getUrlParam('set');
Handlebars.registerHelper('selectSet', function(){
if (s == 1){
return 'set_1'
} else if (s == 2) {
return 'set_2'
} else {
return 'set_1'
}
});
// In my HTML
{{#each (lookup . (selectSet))}}
{{name}}
{{/each}}

Protractor: How to find an element in an ng-repeat by text?

I'm looking to get a specific element inside an ng-repeat in protractor by the text of one of its properties (index subject to change).
HTML
<div ng-repeat="item in items">
<span class="item-name">
{{item.name}}
</span>
<span class="item-other">
{{item.other}}
</span>
</div>
I understand that if I knew the index I wanted, say 2, I could just do:
element.all(by.repeater('item in items')).get(2).element(by.css('.item-name'));
But in this specific case I'm looking for the 'item in items' that has the specific text (item.name) of say "apple". As mentioned, the index will be different each time. Any thoughts on how to go about this?
public items = element.all(by.binding('item.name'))
getItemByName(expectedName) {
return this.items.filter((currentItem) => {
return currentItem.getText().then((currentItemText) => {
return expectedName === currentItemText;
});
}).first();
}
And invoke method like that this.getItemByName('Item 1'). Replace Item 1 with expected string.
function elementThere(specificText, boolShouldBeThere){
var isThere = '';
element.all(by.repeater('item in items')).each(function (theElement, index) {
theElement.getText().then(function (text) {
// Uncomment the next line to test the function
//console.log(text + ' ?= ' + specificText);
if(text.indexOf(specificText) != -1){
element.all(by.repeater('item in items')).get(index).click();
isThere = isThere.concat('|');
}
});
});
browser.driver.sleep(0).then(function () {
expect(isThere.indexOf('|') != -1).toBe(boolShouldBeThere);
});
}
it('should contain the desired text', function () {
elementThere('apple', true);
}
Does this fit your needs?
I was able to solve this by simplifying #bdf7kt's proposed solution:
element.all(by.repeater('item in items')).each(function(elem) {
elem.getText().then(function(text) {
if(text.indexOf('apple') != -1) {
//do something with elem
}
});
});
Also, this particular solution doesn't work for my use case, but I'm sure will work for others:
var item = element(by.cssContainingText('.item-name', 'apple'));
//do something with item

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>

AngularJS - Changing a variable inside a controller method doesn't update the $scope variable

I want to create a method in my controller to set to null different variables from my controller $scope. So I've this in my controller :
FootCreator.controller('FooController', function($scope) {
$scope.zoo = {
id: 1,
name: 'Lorem',
};
$scope.foo = {
id: 2,
title: 'bar',
};
$scope.deleteProperty = function(property) {
property = null;
};
});
And in my HTML I call it this way (for example) :
<a ng-click="deleteProperty(zoo)" class="remove icon-remove" title="Remove"></a>
When I console.log() the $scope.zoo it's not set to null. I think I must do something bad but can't find what. I try to do that not to have a deleteZoo(), deleteFoo() etc.
Thanks for the help/tips !
In your deleteProperty method, you are just setting the property parameter to null and this is never going to have any effect on your scope.
A simplified example of what you're doing here is:
$scope.zoo = { id: 1, name: 'Lorem' };
var property = $scope.zoo;
property = null;
console.log($scope.zoo); // previous line had no effect on $scope.zoo
I would suggest passing the property name as a string instead of the property itself. Then you can do this:
$scope.deleteProperty = function(property) {
delete $scope[property];
};
<a ng-click="deleteProperty('zoo')" class="remove icon-remove"
title="Remove"></a>
If you really want to pass the property itself (like you're doing in your HTML), you'd need to loop through all the properties to find the one that matches:
$scope.deleteProperty = function(property) {
for (var p in $scope) {
if ($scope.hasOwnProperty(p) && $scope[p] === property) {
delete $scope[p];
}
}
};

How can i get this ng-option to init with selected object value?

I´m trying to start this select with a predefined option selected. But i need to use as value an object like you can see in my code. I need to get an id in data.selected.
index.html
<div ng-controller="MyCtrl">{{data|json}}
<select ng-model="data.selected"
ng-options="p.id.another group by p.id.proxyType for p in proxyOptions" >
</select>
</div>
app.js
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.proxyOptions = [{
id: { proxyType: 'None', another: 1 }
}, {
id: { proxyType: 'Manual', another: 2 }
}, {
id: { proxyType: 'Automatic', another: 3 }
}];
$scope.data = {};
$scope.data.selected = $scope.proxyOptions[0].id; }
Fiddle
http://jsfiddle.net/fh01qndt/2/
New Fiddle based on Darren comments
http://jsfiddle.net/fh01qndt/5/
It works but i still need to specify the selected options this way:
$scope.data.selected = {proxyType: 'Manual', another: 2};
Use $scope.data.selected = $scope.proxyOptions[0] instead. Your way is creating another object which is different from your proxy options.
You just changed your questions code...Please don't do that.
Remove the .id from your assignment - ng-model will be the entire option object not just the Id
Here is your exact fiddle, but with the .id removed from your assignment.
JSFiddle
UPDATE
Ok, So having looked again at your code I have tried to understand what you're trying to achieve - i also noticed that I misread your original JSON object regarding the id - sorry; i saw id and assumed it referred to "an id" and not an object..
However, I think what you're trying to do is set your selected option in code, so you would need to search through the list and find your match, no?
If that's the case, then this fiddle shows ng-init() calling a function to do just that.
Any good to you? Another Fiddle, using ng-init
IF U NEED ONLY THE PLEAE CHECK THIS ONE
$scope.proxyOptions = {
'1': 'None',
'2': 'Manual',
'3': 'Automatic'
};
$scope.data.selected = '1';
<select ng-model="data.selected" ng-options="key as value for (key , value) in proxyOptions" >
</select>
do like this:
var myApp = angular.module('myApp', []);
function DataController($scope) {
$scope.proxyOptions = [{
id: { proxyType: 'None', another: 1 }
}, {
id: { proxyType: 'Manual', another: 2 }
}, {
id: { proxyType: 'Automatic', another: 3 }
}];
$scope.data.selected=$scope.proxyOptions[0];
}
see jsfiddle

Resources