Angular Ng-If Ng-Style not changing the table font colour - html

I have the following code which is an ionic list which populates the data retrieved. Im trying to colour code it into different colours based on the Status reponse.
<ion-list>
<ion-item ng-repeat="test in tests" class ="item-text-wrap" style="height:40%">
<a href="#/tab/test/test-detail/{{test.ID}}">
<div style="width:80%; float:left;">
<table>
<span ng-if="test.Status == 'Cleared'" ng-style="color:green">
<tr>
<td> <strong>Remark: </strong></td>
<td style="padding:3px">{{test.Remark}}</td>
</tr>
<tr>
<td><strong>Status:</strong></td>
<td style="padding:3px">{{test.Status}}</td>
</tr>
</span>
</table>
</div>
</ion-item>
</ion-list>
But the colour of the table data still does not change. What could be the problem? Am i using the ng-if and ng-style wrongly? Thanks!
Update 1: Using the insights provided by #SSH, i updated my controller with the following codes:
Html:
<ion-list>
<ion-item ng-repeat="test in tests" class ="item-text-wrap" style="height:40%">
<a href="#/tab/test/test-detail/{{test.ID}}">
<div style="width:80%; float:left;">
<table>
<span ng-style="calculateStyle()">
<tr>
<td> <strong>Remark: </strong></td>
<td style="padding:3px">{{test.Remark}}</td>
</tr>
<tr>
<td><strong>Status:</strong></td>
<td style="padding:3px">{{test.Status}}</td>
</tr>
</span>
</table>
</div>
</ion-item>
</ion-list>
Controller:
$scope.calculateStyle = function() {
var style={}
console.log('test3: '+$scope.tests.Status);
console.log('test6: '+$scope.Status);
if ($scope.Status == 'Cleared') {
style.color='green';
console.log('Viola');
}
else{
console.log('GG');
}
return style;
}
})
But the result returned in the controllers are still null/undefined. test3 and test6 returned me 'undefined' while the If statement returned me 'GG'. What could be the problem? Thanks!
Update 2: Using SSH answers, i modified to the following:
Html:
<span ng-style="calculateStyle(test)">
Controller:
$scope.calculateStyle = function(test) {
var style={}
if (test.Status == 'Cleared') style.color='green';
return style;
}
But the test variable at the controller is still undefined. Using $scope.test doesn't work too. What could be the problem?

Yes you do use it wrongly. You need to pass an object consisting of style names and conditions:
<span ng-style="{color:(test.Status == 'Cleared')?'green'}">
or better use a function in your controller to calculate and return style object, to keep your template clean:
<span ng-style="calculateStyle(test)">
and then in your controller definition
$scope.calculateStyle = function(test) {
var style={}
if (test.Status == 'Cleared') style.color='green';
return style;
}

Related

Table row on click function is not working in Angular7

I am trying to call a function whenever i click a row in an HTML table but it is not working and it is not giving any errors.
I've tried several things, and online code shows that the way i try it, it should be working.
My code is as following:
Html:
<h2>Userstories</h2>
<button (click)="onNewStory()">New Story</button>
<table>
<tr *ngFor="let story of userstories" ng-click="onUpdate(story)" [class.selected]="story === selectedStory">
<td>{{story.id}}</td>
<td>{{story.name}}</td>
<td><button ng-click="onUpdate(story)">Click me!</button></td>
</tr>
</table>
<app-userstory-detail [story]="selectedStory"></app-userstory-detail>
And my .ts looks like this:
selectedStory: UserStory;
onNewStory() {
var newStory = {id:this.userstories[this.userstories.length-1].id+1, name:"", description:"Deze is nieuw", status:"open", owner:USERS[1]};
this.userstories.push(newStory);
this.selectedStory = newStory;
}
onUpdate(userstory: UserStory): void {
this.selectedStory = userstory;
console.log(this.selectedStory);
}
Currently my console is not printing the log, when i try to call the onUpdate method. The expected result is to see some output in the logs, but i have no clue why it is not firing the onUpdate method.
In angular 7 you can use (click) which is similar to ng-click of Angular JS.
Try:
<h2>Userstories</h2>
<button (click)="onNewStory()">New Story</button>
<table>
<tr *ngFor="let story of userstories" (click)="onUpdate(story)" [class.selected]="story === selectedStory">
<td>{{story.id}}</td>
<td>{{story.name}}</td>
<td><button (click)="onUpdate(story)">Click me!</button></td>
</tr>
</table>
<app-userstory-detail [story]="selectedStory"></app-userstory-detail>
StackBlitz Demo
ng-click is actually for AngularJS (1.x)
You want to use (click) which is for Angular.
DOCUMENTATION: https://angular.io/guide/ajs-quick-reference#ng-click
The event is fired twice. In <tr> and in <button>.
Try this:
<h2>Userstories</h2>
<button (click)="onNewStory()">New Story</button>
<table>
<tr *ngFor="let story of userstories" [class.selected]="story === selectedStory">
<td>{{story.id}}</td>
<td>{{story.name}}</td>
<td><button (click)="onUpdate(story)">Click me!</button></td>
</tr>
</table>
<app-userstory-detail [story]="selectedStory"></app-userstory-detail>

PrimeNG Turbotable expand by default

I have a PrimeNg turbotable with row expansion feature.
How can I expand the rows by default.
Here is my Code :
HTML
<p-table [columns]="cols" [value]="cars" dataKey="vin">
<ng-template pTemplate="header" let-columns>
<tr>
<th style="width: 2.25em"></th>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-expanded="expanded" let-columns="columns">
<tr>
<td>
<a href="#" [pRowToggler]="rowData">
<i [ngClass]="expanded ? 'fa fa-fw fa-chevron-circle-down' : 'fa fa-fw fa-chevron-circle-right'"></i>
</a>
</td>
<td *ngFor="let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
<ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
<tr>
<td [attr.colspan]="columns.length + 1">
<div class="ui-g ui-fluid" style="font-size:16px;padding:20px">
<div class="ui-g-12 ui-md-3" style="text-align:center">
<img [attr.alt]="rowData.brand" src="assets/showcase/images/demo/car/{{rowData.brand}}.png">
</div>
<div class="ui-g-12 ui-md-9">
<div class="ui-g">
<div class="ui-g-12">
<b>Vin:</b> {{rowData.vin}}
</div>
<div class="ui-g-12">
<b>Vin:</b> {{rowData.color}}
</div>
<div class="ui-g-12">
<b>Brand:</b> {{rowData.brand}}
</div>
<div class="ui-g-12">
<b>Color:</b> {{rowData.color}}
</div>
</div>
</div>
</div>
</td>
</tr>
</ng-template>
</p-table>
Ts
export class TableRowExpansionDemo implements OnInit {
cars: Car[];
cols: any[];
constructor(private carService: CarService) { }
ngOnInit() {
this.carService.getCarsSmall().then(cars => this.cars = cars);
this.cols = [
{ field: 'vin', header: 'Vin' },
{ field: 'year', header: 'Year' },
{ field: 'brand', header: 'Brand' },
{ field: 'color', header: 'Color' }
];
}
}
}
I tried using expandedRowKeys attribute, but it is not working for me.
What am I missing here?
Thanks
Update: For Version >7.x
Setting value to 1 won't work on version 7+ use boolean(true/false)
const thisRef = this;
this.cars.forEach(function(car) {
thisRef.expandedRows[car.vin] = true;
});
Working StackBlitz
For Version <7.x
I tried using expandedRowKeys attribute
Yes you're right. So add [expandedRowKeys]="expandedRows"> to p-table element :
<p-table [columns]="cols" [value]="cars" dataKey="vin" [expandedRowKeys]="expandedRows">
and then, you just need to fill expandedRows object with vin values of the rows you want to expand (because dataKey is vin).
Because you want all rows to be expanded, you can fill it like that :
const thisRef = this;
this.cars.forEach(function(car) {
thisRef.expandedRows[car.vin] = 1;
});
in order to have something like
expandedRows = {"dsad231ff": 1, "gwregre345": 1, ...}
See working Plunker
In the accepted answer, the expandedRows mapping to the turbo table expandedRowKeys is one way i.e. it can set the state of rows at the time of loading only.
If someone want to collapse or expand it after the table is loaded, you can directly edit the 'expandedRowKeys' variable by passing the table reference from the html.
Define Your table with a reference variable #dt
<p-table #dt [columns]="cols" [value]="cars" dataKey="vin">
Edit your table body like this to get a on click function trigger
<ng-template pTemplate="body" let-rowData let-expanded="expanded" let-columns="columns">
<tr>
<td>
<a href="#" [pRowToggler]="rowData">
<i [ngClass]="expanded ? 'fa fa-fw fa-chevron-circle-down' : 'fa fa-fw fa-chevron-circle-right'"></i>
</a>
</td>
<td *ngFor="let col of columns">
<a >
<span (click)="onItemClick(rowData, dt)">
{{rowData[col.field]}}
</span>
</a>
</td>
</tr>
</ng-template>
in your TS file add the function as
onItemClick(rowData:any, dt:any) {
if(dt.expandedRowKeys[rowData._id]){
dt.expandedRowKeys[rowData._id] = 0;
}
else {
dt.expandedRowKeys[rowData._id] = 1;
}
}
This approach gives you more freedom in changing state of table on a trigger of event from outside of table and expanding or collapsing multiple rows at once.
After hitting many solution i tried and found easiest way to resolve
<p-table [columns]="cols" [value]="cars" dataKey="vin" [expandedRowKeys]="expandedRows">
Replace datakey value to your unique id key from list of objects fetched from service or http calls.
<p-table [columns]="cols" [value]="repaymentsList" dataKey="id" expandableRows="true" rowExpandMode="single" [responsive]="true">

On click of each row,corresponding row data should get print in Angular js

Hello friends, I am new in angular js.I need help to print the each
row's data on click of button assigned to each row. Below is my
code.
HTML code:
List item
enter code here
<div class="jumbotron">
<table border='1'>
<tr ng-show="reports.length!=0" ng-repeat="report in reports">
<td>{{report.first_name}}</td>
<td>{{report.emp_id}}</td>
<td>{{report.month_calendar_days}}</td>
<td>{{report.pay_days}}</td>
<td>{{report.paid_days}}</td>
<td> 5" ng-repeat="key in noAlphabetSortPlease(report)" style="padding-left:10px;">{{report[key]}}</td>
<td><button ng-click="PrintRow()">Print Row</button></td>
</tr>
</table>
</div> </div>
Controller Code:
angular.module('app', [])
.controller('mainController', ['$scope', '$filter', function($scope,
$filter) {
$scope.noAlphabetSortPlease = function(obj){
return Object.keys(obj);
}
$scope.reports = [{"emp_id":"10001","first_name":"siva","status":1,"month_calendar_days":29,"pay_days":29,"paid_days":21,"salary_head_value1":0,"salary_head_value2":7550,"salary_head_value3":1600,"salary_head_value4":1800,"salary_head_value5":345,"salary_head_value6":6400,"salary_head_value7":5000,"salary_head_value8":31955,"salary_head_value9":1250,"salary_head_value10":12000,"salary_head_value11":6000,"salary_head_value12":47900,"salary_head_value13":15945,"salary_head_value14":4000,"salary_head_value15":2400},
{"emp_id":"10002","first_name":"naren","status":1,"month_calendar_days":29,"pay_days":29,"paid_days":21,"salary_head_value1":15501,"salary_head_value2":7551,"salary_head_value3":1601,"salary_head_value4":1801,"salary_head_value5":346,"salary_head_value6":6401,"salary_head_value7":5001,"salary_head_value8":31957,"salary_head_value9":1251,"salary_head_value10":12001,"salary_head_value11":6001,"salary_head_value12":47907,"salary_head_value13":15950,"salary_head_value14":4001,"salary_head_value15":2401},
{"emp_id":"10003","first_name":"Bhaki","status":1,"month_calendar_days":29,"pay_days":29,"paid_days":21,"salary_head_value1":15502,"salary_head_value2":7552,"salary_head_value3":1602,"salary_head_value4":1802,"salary_head_value5":347,"salary_head_value6":6402,"salary_head_value7":5002,"salary_head_value8":31959,"salary_head_value9":1252,"salary_head_value10":12002,"salary_head_value11":6002,"salary_head_value12":47914,"salary_head_value13":15955,"salary_head_value14":4002,"salary_head_value15":2402}];
$scope.PrintRow=function($index){ window.print();
} }]); </script>
Pass the corresponding object to the function call and overide your reports variable.
<tr ng-show="reports.length!=0" ng-repeat="report in reports">
<td>{{report.first_name}}</td>
<td>{{report.emp_id}}</td>
<td>{{report.month_calendar_days}}</td>
<td>{{report.pay_days}}</td>
<td>{{report.paid_days}}</td>
<td> 5" ng-repeat="key in noAlphabetSortPlease(report)" style="padding-left:10px;">{{report[key]}}</td>
<td><button ng-click="PrintRow(report)">Print Row</button></td>
</tr>
$scope.PrintRow=function(obj){
$scope.reports=[];
$scope.reports.push(obj);
}
Or If you want all data to persist and want to print the corresponding data of each row below the new table.Then you could do something like this
<tr ng-show="reports.length!=0" ng-repeat="report in reports">
<td>{{report.first_name}}</td>
<td>{{report.emp_id}}</td>
<td>{{report.month_calendar_days}}</td>
<td>{{report.pay_days}}</td>
<td>{{report.paid_days}}</td>
<td> 5" ng-repeat="key in noAlphabetSortPlease(report)" style="padding-left:10px;">{{report[key]}}</td>
<td><button ng-click="PrintRow(report)">Print Row</button></td>
</tr>
{{newArray}}
$scope.newArray=[];
$scope.PrintRow=function(obj){
$scope.newArray.push(obj);
}
Format new array to your desire.
<tr ng-show="reports.length!=0" ng-repeat="report in newArray">
<td>{{report.first_name}}</td>
<td>{{report.emp_id}}</td>
<td>{{report.month_calendar_days}}</td>
<td>{{report.pay_days}}</td>
<td>{{report.paid_days}}</td>
<td> 5" ng-repeat="key in noAlphabetSortPlease(report)" style="padding-left:10px;">{{report[key]}}</td>
<td><button ng-click="PrintRow(report)">Print Row</button></td>
</tr>

Populate multiple g:select with an array variable

I am trying to have two multiple select lists that I am trying to do the typical add/remove between the two. I am able to add and remove initially and save the array of values from the second g:select but I cannot seem to repopulate the second g:select when I try to show the user an updated value.
<table class="threecols">
<tr>
<td style="width: 10%">
<g:select multiple="true" id="select1" name="select1" from="${['User','Department','School','Class','User','Id','District']}" disabled="${disabled}"/>
</td>
<td style="width: 10%">
<button type="button" style="margin-left: 12px">Add >>
</button>
<button type="button"><< Remove </button>
</td>
<td style="width: 10%">
<g:select multiple="true" id="select2" name="paramList" from="${report?.paramList}" value="${report?.paramList}" disabled="${disabled}"/>
</td>
</tr>
</table>
and the variable declaration is: String[] paramList
Any help is appreciated.
You need to use JQuery to do this:
$(document).ready(function() {
$('#add').click(function(){
$('#select2 option:selected').each( function() {
$('#select1').append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
$(this).remove();
});
});
$('#remove').click(function(){
$('#select1 option:selected').each( function() {
$('#select2').append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
$(this).remove();
});
});
});
More Info here: Link
I was being stupid and was using report?.paramList when I should have used reportInstance?.paramList since report is just the class where reportInstance was a singular object. Woops.

Knock Out data binding

I have a question about data binding using knockout.
Here's the problem: I have a table, I what I would like to do is that when a row in table is clicked, I want the values of the row to appear in the input fileds which are located above the table.
so here'
<tbody data-bind="foreach: customers">
<tr data-bind="click: doSomething">
<td data-bind="text: date"></td>
<td data-bind="text:staff"></td>
<td data-bind="text: ftype"></td>
<td data-bind="text: value"></td>
<td data-bind="text: message"></td>
</td>
</tr>
</tbody>
In my viewmodel, I have the following function:
doSomething: function(data) {
var self = this;
self.date(data.date);
self.staff(data.staff);
self.ftype(data.ftype);
self.value(data.value);
self.message(data.message);
}
Here's the error I am getting:
["Unable to parse bindings.↵Message: ReferenceError:… is not defined;↵Bindings value: click: doSomething", "views/myView/index", Object]
0: "Unable to parse bindings.↵Message: ReferenceError: doSomething is not defined;↵Bindings value: click: doSomething"
1: "views/myView/index"
2: Object
length: 3
__proto__: Array[0]
Let me know if I need to provide any more details. I will appreciate your help fplks!
A very basic pattern for this type of thing is to have an array of items and a selectedItem observable that you populate when selecting a row.
Then, you can use the with binding around a section to create your editor.
<table>
<tbody data-bind="foreach: customers">
<tr data-bind="click: $root.selectedCustomer">
<td data-bind="text: name"></td>
</tr>
</tbody>
</table>
<hr/>
<div data-bind="with: selectedCustomer">
<input data-bind="value: name" />
</div>
Sample: http://jsfiddle.net/rniemeyer/Z6VPV/
You need to bind your model to the view
var currentViewModel = function(){
this.doSomething = function(data){
var self = this;
self.date(data.date);
self.staff(data.staff);
self.ftype(data.ftype);
self.value(data.value);
self.message(data.message);
}
var viewModel = new currentViewModel();
ko.applyBindings(viewModel);