passing "this" in ng-repeat content - angularjs

I am using ng-repeat in table for generating the table rows dynamically. I need to call a function with "this" keyword when user clicks on a check box in the table. When I am passing this as an argument its coming undefined on the js side. please help me below is my code
<table class="codelisttab">
<tr><th></th><th>Employee Name</th><th>Employee Id</th></tr>
<tr data-ng-repeat="emp in employees">
<td style="width:20px;"><a data-ng-click="updateEmployeeList(emp.empid, this)" class="ui-multiselect-box commonMultiSelectClass unCatMultiselectColorSelected" id="unCatMulti_109812"></a></td>
<td>{{emp.name}}</td><td>{{emp.empid}}</td>
</tr>
<tr colspan="3"><th style="text-align:center;"><input type="button" data-ng-click="addGroup()" value="Create Group"></th></tr>
My js code:
$scope.updateEmployeeList = function(empid, obj){
var i = $scope.employeeList.indexOf(empid);
if(i <= -1){
$scope.employeeList.push(empid);
obj.style.backgroundColor="#89e3f9";
}
else{
obj.style.backgroundColor="#0e5061";
$scope.employeeList.splice(i,1);
}
console.log($scope.employeeList.toString());
}

If you are gonna need a special context to the function updateEmployeeList you can always bind the specific context previously, for instance:
$scope.updateEmployeeList = $scope.updateEmployeeList.bind(this);
And it will be executed with the right context.
However, this is not very angular-ish.

What do you expect this to be? If you want the element yo need to pass $event to ng-click and get event.currentTarget: get original element from ng-click
<a data-ng-click="updateEmployeeList(emp.empid, $event)" class="ui-multiselect-box commonMultiSelectClass unCatMultiselectColorSelected" id="unCatMulti_109812"></a>
$scope.updateEmployeeList = function(empid, $event){
var i = $scope.employeeList.indexOf(empid),
obj = $event.currentTarget;
if(i <= -1){
$scope.employeeList.push(empid);
obj.style.backgroundColor="#89e3f9";
}
else{
obj.style.backgroundColor="#0e5061";
$scope.employeeList.splice(i,1);
}
console.log($scope.employeeList.toString());
}

Related

Conditional css class assign in angular 2

I have a grid with checkbox, I am putting checked values in an array (currentFocusedRow), now I want to assign activeRow class to the checked row:
// app.ts
class contact {
public contactlist = [{icontact_id: "contact1"}, {icontact_id: "contact2"}, {icontact_id: "contact3"}, {...}];
public currentFocusedRow = ["contact2", "contact3"];
}
// app.html
<tr *ngFor="let contact of contactlist"
[class.activeRow]="contact.icontact_id == currentFocusedRow">
...
</tr>
now since currentFocusedRow is an array i can't simply check like that (contact.icontact_id == currentFocusedRow) there should be something to check if the value is present in that array or not like indexOf.
I think this should work for you:
Typescript
isActive(id) {
return this.currentFocusedRow.indexOf(id) !== -1
}
HTML
<tr *ngFor="let contact of contactlist"
[class.activeRow]="isActive(contact.icontact_id)">
</tr>
You can use index of the object that is current object, by using:
<tr *ngFor="let contact of contactlist; let i = index">
Which will enable you to get those indexes.
Apart from that, you can just use NgClass directive.
Checking with indexOf in directive itself worked, this is pretty amazing that we can use this JS methods directly in DOM:
<tr *ngFor="let contact of contactlist;"
[class.activeRow]="currentFocusedRow.indexOf(contact.icontact_id) != '-1'">
</tr>

Use AngularJS Variable, where another AngularJS Variable matches its ID

I have an ng-repeat statement where I want to show an image. The image however, should be chosen from where the ng-repeat's ID matches the image object's ID.
I am unsure of how to do this properly, here is psuedo code of what I am trying to do.
<tr ng-repeat="user in rosterData | orderBy:'name'">
<img ng-src="{{champion.imagename WHERE user.id = champion.id}} />
</tr>
Remember that champion.id is an object of champions, so I want to make sure I get the right champion.name to match with the right champion.id when it matches the current ng-repeat user.id
It would be better if you could check those logic inside the controller:
<tr ng-repeat="user in rosterData | orderBy:'name'">
<img ng-src="{{getImage(user.id)}} />
</tr>
In your controller:
$scope.getImage = function(userId) {
var image = "defaultimage";
$scope.champions.forEach(function(champion) {
if(champion.id===userId) {
image = champion.image;
}
});
return image;
}
You will have to put a method in "ng-src" statement, pass the id as a parameter - > iterate array, find match and so on.
Method should be added in controller to $scope property, than just call it :)

calling a function from ng-repeat with the object from the current scope

I'm trying to call a function (from a non event element) from a ng-repeat to feed an array of data to an autocomplete element (using https://github.com/JustGoscha/allmighty-autocomplete).
It's to generate a kind of logic system :
type(listbox) | comparator (eg:>=) (listbox) | value(autocomplete)
And several of those object can be listed on a webpage to get some complex logic
type=value && type2>value3 || ...
Depending on type and comparator, values are different.
The code so far (simplified):
<div class="comparator" ng-repeat="comp in container.comparators">
<select ng-model="comp.type"><option ng-repeat="i in type_options" value="{{i.value}}" ng-selected="{{i.value==comp.type}}">{{i.label}}</option></select>
<select ng-model="comp.comparator"><option ng-repeat="i in comp_options|filter:typeMatch(comp)" value="{{i.value}}" ng-selected="{{i.value==comp.comparator}}">{{i.label}}</option></select>
<autocomplete class="autocomplete" data="" attr-placeholder="Entrez votre valeur" click-activation="true" on-type="**updateValue**" ng-model="comp.value"></autocomplete>
</div>
updateValue is the function to call, but i need to know the current object (comp from the ng-repeat) on which i am to send the right array of value.
I tryed to send an existing array to avoid "digest loop"
$scope.updateValue = function(crit){
for(var i=0;i
I also tryed to do a function that return a function that return the array :DDDDD :
$scope.updateValue = function(crit){
return function(value/*not used*/){
for(var i=0;i<$scope.comp_options.length;i++) {
if($scope.comp_options[i].value===crit.comparator){
$scope.value_elements=$scope.comp_options[i].info;
break;
}
}
return $scope.value_elements;
};
};
Replacing the autocomplete object with :
if I console.log(comp), I see that I can get my object, but I get a digest loop ...
Is there a way to know the object of the "line" I was called from ?
Thx (i'm a total newbie in angular, but so far, i've been unable to find how to retrieve that information ... is that even possible :) ?).
Access it using $index ? Example below. You can then use the index to access it
<tr ng-repeat="user in uc.users track by $index">
<td>{{user.id}}</td>
<td>{{user.first_name}}</td>
<td>{{user.last_name}}</td>
<td>{{user.email}}</td>
<td>{{user.department}}</td>
<button ng-click="uc.open(user.id, $index);">Open</button>
</tr>

angular filter name as variable

I'm designing universal table that reads data and columns from ajax.
In columns description is also filter name which angular should use for a specific column.
But in HTML templates I can't use variables for filter names:/
Is there a solution for that? Or should I code javascript loop with data source?
Here is code example:
<tr ng-repeat="item in data">
<td ng-repeat="col in cols">
{{item[col.source]}}
<span ng-if="col.ngFilter">
{{col.ngFilter}} // ex. "state" filter
{{item[col.source]|col.ngFilter}} //is not working - is looking for "col.ngFilter" not "state" filter.
</span>
</td>
</tr>
You cannot do it in your HTML. First, you need to apply the filter in your controller.
function MyCtrl($scope, $filter) {
$scope.applyFilter = function(model, filter) {
return $filter(filter)(model);
};
}
Then, in your HTML:
Instead of
{{item[col.source]|col.ngFilter}}
use
{{applyFilter(item[col.source], col.ngFilter)}}
For anyone looking to do something like
{{applyFliter(item[col.source], col.ngFilter)}}
where ngFilter might contains some colon separated parameters such as
currency:"USD$":0
I ended up writing this little helper
function applyFilter (model, filter){
if(filter){
var pieces = filter.split(':');
var filterName = pieces[0];
var params = [model];
if(pieces.length>1){
params = params.concat(pieces.slice(1));
}
return $filter(filterName).apply(this,params);
}else{
return model;
}
}

How to ng-repeat into html table with multiple levels of json?

I have an object of social media stats. I'm trying to ng-repeat them into a table. Here's my plunker.
HTML:
<table>
<tr ng-repeat="(metric, metricData) in data">
<td>{{metric}}</td>
<td>{{metricData}}</td>
</tr>
</table>
Controller object:
$scope.data = { buzz:0,
Delicious:121,
Facebook:
{
like_count: "6266",
share_count: "20746"
},
GooglePlusOne:429,
LinkedIn:820,
Twitter:4074
};
I run into a problem when I get to the Facebook results. Within the <td> that entire object gets displayed (as it should be with how I have my code setup). But what I'd rather have happen is to repeat through that object and display the key and value in the cell.
I tried doing something looking to see if metricData is an object and doing some sort of ng-repeat on that. But I wasn't having luck with that. Any idea on how I can display the inner object (keys & value) within the cells?
You can define a scope function returning the type of metricData :
$scope.typeOf = function(input) {
return typeof input;
}
And then you can display it according to its type :
<tr ng-repeat="(metric, metricData) in data">
<td>{{metric}}</td>
<td ng-switch on="typeOf(metricData)">
<div ng-switch-when="object">
<div ng-repeat="(key, value) in metricData">
<span>{{key}}</span>
<span>{{value}}</span>
</div>
</div>
<span ng-switch-default>{{metricData}}</span>
</td>
</tr>
You can see it in this Plunker
Sounds like you'll need a specific directive that wires up children to be recursive, take a look at this example: Recursion in Angular directives
What you'd check on is if what you need to repeat is an object and not a value, then add the new element compile it, and start the process over again.
I'm assuming you want each of those values to have their own line but you don't explain exactly how you want it to work. I think the matter would best be handled by passing a clean version of what you want to the ng-repeat directive. I'm assuming you want two rows for facebook in your sample. You could create a filter to flatten the metrics so there are properties "Facebook_like_count" and "Facebook_share_count" (PLUNKER):
app.filter('flatten', function() {
function flattenTo(source, dest, predicate) {
predicate = predicate || '';
angular.forEach(source, function(value, key) {
if (typeof(value) == 'object') {
flattenTo(value, dest, predicate + key + '_');
} else {
dest[predicate + key] = value;
}
});
}
return function(input) {
var obj = {};
flattenTo(input, obj, '');
return obj;
}
});
Then your repeat can use the filter:
<tr ng-repeat="(metric, metricData) in data|flatten">

Resources