I have a few different working pieces here, but I'm struggling with how to to bring them all together. I currently have a list of elements sorted by their health status (value given between 0 and 100).
For each element, I would like to color the background based on its health status. So, status = 0 would mean I have a fill color of red; status=50 yellow; status=100 green.
In something like d3, I would accomplish that with the following code (which, is a great trick, by the way):
/*normalize input between 0 and 100 to hsl color scale -- so 0=0 and 100 = 120, where hue=0 is red and hue=120 is green */
var hueScale = d3.scale.linear().domain([0,100]).range([0,120]);
.style("fill", function(d){
var hslColor = 'hsl(' + hueScale(d.status)) + ', ' + (100) + '%, ' + (50) + '%, ' + (1) + ')';
return d3.rgb(hslColor).toString().toUpperCase(); })
but here, I'm dealing with a normal list, not a d3 graphic.
I've also made use of ng-class in the past to specify a dynamic color:
$scope.getClass = function(status) {
if (status == (100)) {
return "good-feed";
} else {
return "bad-feed";
}
};
and
ng-class="[getClass(item.status)]"
I need to combine both of these techniques. I think using ng-class in a similar way to what I have is what I need to do, but I'm not sure how to get the color change function to work without being needlessly complicated.
Any thoughts?
EDIT
Both my current code snippets above work, but the issue is I want to be able to iterate through all status values between 0 and 100, not just handle an either-or situation.
For example:
Item 1 with status of 23 (approx. color: orange)
Item 2 with status of 45 (approx. color: yellow-orange)
Item 3 with status of 67 (approx. color: yellow-green)
Item 4 with status of 99 (approx. color: green)
And so on. Now, I COULD write my color function for ng-class to look something like this (update: this doesn't work) :
$scope.getClass = function(status) {
if (status <= (10)) {
return "dark-red";
} else if (10 < status <= 20){
return "red-orange";
// continue pattern for all intervals until 100 is reached
} else {
return "undefined-grey";
}
};
But manually going through like that for each value seems clunky. Is there any way to make this smoother (akin to the d3 solution)?
just use this
ng-class="{'good-feed' : item.status == 100,'bad-feed' : item.status != 100 }"
Alright, so this answer is the best I've got for now. It still requires some work to get this to do exactly what I would like, but it's on the right track:
I ended up usuing jquery to break apart colors based on value (like I was attempting to do with my ng-class function)
See my JSFiddle for details.
$(document).ready(function () {
var cell = $('ul.list-view li');
cell.each(function() {
var cell_value = parseFloat($(this).html().slice(0, -1));
// Positief
if ((cell_value >= 0) && (cell_value <= 0.3)) {
$(this).css({'background-color' : '#7FFF95'});
}
else if ((cell_value >= 0.31) && (cell_value <= 0.5)) {
$(this).css({'background-color' : '#66FF7C'});
}
else if ((cell_value >= 0.51) && (cell_value <= 0.7)) {
$(this).css({'background-color' : '#4DFF63'});
}
else if ((cell_value >= 0.71) && (cell_value <= 1)) {
$(this).css({'background-color' : '#33F749'});
}
else if ((cell_value >= 1.01) && (cell_value <= 1.5)) {
$(this).css({'background-color' : '#1ADE30'});
}
else if (cell_value >= 1.5) {
$(this).css({'background-color' : '#00CC66'});
}
// Negatief
else if ((cell_value >= -0.01) && (cell_value <= -0.2)) {
$(this).css({'background-color' : '#F6ADAC'});
}
else if ((cell_value >= -0.31) && (cell_value <= -0.5)) {
$(this).css({'background-color' : '#F18483'});
}
else if ((cell_value >= 0.51) && (cell_value <= -0.7)) {
$(this).css({'background-color' : '#EF706E'});
}
else if ((cell_value >= -0.71) && (cell_value <= -1)) {
$(this).css({'background-color' : '#ED5B5A'});
}
else if ((cell_value >= -1.01) && (cell_value <= -1.5)) {
$(this).css({'background-color' : '#EB4745'});
}
else if (cell_value >= -1.5) {
$(this).css({'background-color' : '#E93331'});
}
});
Related
Hello there I need help in converting this 'if-else' with 'or' condition into conditon that can be used in ng-class.
This here is my ng-class with condition, but it's not working correctly.
<span ng-class="{'green': work > toWork,
'red': work < toWork,
'black': work == toWork || overall == '-'}">
{{overall = showMonthly(work = (workers | getMonthValue: dts.value),
toWork = getMonthlyToWork(member.id, dts.value))}}
</span>
this is the condition I'd like to apply:
if (work > toWork) {
return "green";
}else if (work < toWork) {
return "red";
}else if (work == toWork || overall == "-") {
return "black";
}
You don't need ng-class for that, you just need to put the logic inside a method in your $scope, like below
$scope.getClass = function(work, toWork, overall){
if (work == toWork || overall == "-"){
return "black";
}else if (work < toWork) {
return "red";
}else if(work > toWork) {
return "green";
}
}
and in your view, call it like this
<span class="{{getClass(work, toWork, overall)}}"></span>
<span ng-class="{'green': work > toWork,
'red': work < toWork,
'black': (work == toWork || overall == '-')}">
...
</span>
Check this. (You have got a spell missing in your conditional statement)
Happy coding!
This question already has answers here:
Sorting an array of objects by property values
(35 answers)
Closed 5 years ago.
I have a page with one list from a JSON file. I want to add a sort button functionality. Below is my code of .ts , .html and picture of console.log of the array.
home.ts code:
this._servall.myservice(this.taskdesc).subscribe(data => {
console.log(data);
this.displaylist = data;
home.html code:
<ion-list no-lines *ngFor="let list of displaylist;let i=index;" >
<ion-item>
<p>{{list.TASKDESC}}</p>
<p>{{list.PRIMARY}}</p>
<p>{{list.DEADLINE_DT}}</p>
</ion-item>
</ion-list>
I want to sort the list with list.PRIMARY //this is a name
I want to sort the list with list.DEADLINE_DT // in increasing order, this is date
Below is the console.log image of this.displaylist array
Create one pipe for sorting
orderbypipe.ts
/*
* Example use
* Basic Array of single type: *ngFor="#todo of todoService.todos | orderBy : '-'"
* Multidimensional Array Sort on single column: *ngFor="#todo of todoService.todos | orderBy : ['-status']"
* Multidimensional Array Sort on multiple columns: *ngFor="#todo of todoService.todos | orderBy : ['status', '-title']"
*/
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({ name: 'order', pure: false })
export class OrderBy implements PipeTransform {
static _orderByComparator(a: any, b: any): number {
if ((isNaN(parseFloat(a)) || !isFinite(a)) || (isNaN(parseFloat(b)) || !isFinite(b))) {
//Isn't a number so lowercase the string to properly compare
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
}
else {
//Parse strings as numbers to compare properly
if (parseFloat(a) < parseFloat(b)) return -1;
if (parseFloat(a) > parseFloat(b)) return 1;
}
return 0; //equal each other
}
transform(input: any, [config = '+']): any {
if (!Array.isArray(input)) return input;
if (!Array.isArray(config) || (Array.isArray(config) && config.length == 1)) {
var propertyToCheck: string = !Array.isArray(config) ? config : config[0];
var desc = propertyToCheck.substr(0, 1) == '-';
//Basic array
if (!propertyToCheck || propertyToCheck == '-' || propertyToCheck == '+') {
return !desc ? input.sort() : input.sort().reverse();
}
else {
var property: string = propertyToCheck.substr(0, 1) == '+' || propertyToCheck.substr(0, 1) == '-'
? propertyToCheck.substr(1)
: propertyToCheck;
return input.sort(function(a: any, b: any) {
return !desc
? OrderBy._orderByComparator(a[property], b[property])
: -OrderBy._orderByComparator(a[property], b[property]);
});
}
}
else {
//Loop over property of the array in order and sort
return input.sort(function(a: any, b: any) {
for (var i: number = 0; i < config.length; i++) {
var desc = config[i].substr(0, 1) == '-';
var property = config[i].substr(0, 1) == '+' || config[i].substr(0, 1) == '-'
? config[i].substr(1)
: config[i];
var comparison = !desc
? OrderBy._orderByComparator(a[property], b[property])
: -OrderBy._orderByComparator(a[property], b[property]);
//Don't return 0 yet in case of needing to sort by next property
if (comparison != 0) return comparison;
}
return 0; //equal each other
});
}
}
}
Html
<ion-list no-lines *ngFor="let list of displaylist | order : ['+PRIMARY'];let i=index;" >
For more details see this http://www.fueltravel.com/blog/migrating-from-angular-1-to-2-part-1-pipes/
Hi I need to convert or use the sent integer value from the checkboxes at the reserve page to the view/print transaction page.
Please see my old question:
How to add IDs of a checkbox in angular js
I am able to get the values from the database and display it on the view page the only problem is that the checkboxes are null. There are 5 checkboxes on the reservation page (Laptop, Headset, Projector, Tablet, Speakers) so the possible combinations are 32 that's why i used to send an integer from 0 - 31 to the database because there's only one column for the reserved items.
I have successfully manage (with the help of this community) to post and get values from the database.
Now please help me to convert/use that INT value to automatically set the checkbox value to true if it was checked by the user on the reserve page.
Example:
Laptop = 1; Headset = 2; Projector = 4; Tablet = 8; Speakers = 16
The user checks (reserve page)
✓ Laptop, Headset, ✓ Projector, Tablet, ✓ Speakers
The value on the DB: 21
One the view/print page
I need to use the int value on the DB (which is 21) to automatically check the checkbox ✓ Laptop, Headset, ✓ Projector, Tablet, ✓ Speakers in read-only disabled mode .
So far this is my code in html and controller:
function getReservedRequestsById(reservedRequestId) {
var key = reservedRequestId;
return dataservice.getReservedRequests(key).then(function (data) {
vm.ReservedRequestId = data.data;
console.log(vm.ReservedRequestId);
logger.info('ACTIVATED');
//CheckBox
if (vm.ReservedRequestId.Items > 15) {
$scope.chkItems.forEach(function (Item) {
if (Item.id == 16) {
Item.value = true;
}
})
}
else if ((16 > vm.ReservedRequestId.Items > 7) || (32 > vm.ReservedRequestId.Items > 23)) {
$scope.chkItems.forEach(function (Item) {
if (Item.id == 8) {
Item.value = true;
}
})
}
else if ((8 > vm.ReservedRequestId.Items > 3) || (16 > vm.ReservedRequestId.Items > 11) || (24 > vm.ReservedRequestId.Items > 19) || (32 > vm.ReservedRequestId.Items > 27)) {
$scope.chkItems.forEach(function (Item) {
if (Item.id == 4) {
Item.value = true;
}
})
}
// AND also for 1 & 2 i did not put it here because i would like to just test if it is working on the three check boxes. If it is working i'll just add the other two
}
<md-input-container class="md-block" flex-gt-sm>
<label class="force-input-label">Items</label>
</br>
<div ng-repeat="chkItem in chkItems">
<md-checkbox name="chkItem.name" ng-model="chkItem.value" readonly>{{chkItem.name}}
</div>
</md-input-container>
it is not currently working
Need help and advice
Not good in english as well as in angularjs/web development : )
your help is greatly appreciated!
I fixed your code. I only kept the logic you provided. The problem was that 16 > x > 7 is not a correct syntax in javascript. You have to use &&.
//Laptop = 1; Headset = 2; Projector = 4; Tablet = 8; Speakers = 16
var chkItems = [{
id: 1,
name: 'Laptop',
value: null,
}, {
id: 2,
name: 'Headset',
value: null
}, {
id: 4,
name: 'Projector',
value: null
}, {
id: 8,
name: 'Tablet',
value: null
}, {
id: 16,
name: 'Speakers',
value: null
}];
var items = 21;
if (items >= 16) {
selectItem(16);
}
if ((items < 16 && items > 7) || (items < 32 && items > 23)) {
selectItem(8);
}
if ((items < 8 && items > 3) || (items < 16 && items > 11) || (items < 24 && items > 19) || (items < 32 && items > 27)) {
selectItem(4);
}
console.log(chkItems);
function selectItem(id) {
chkItems.map(function(elem) {
if (!elem.value)
elem.value = (elem.id === id);
return elem;
});
}
I'm at my witsend with this problem. I'm building Conway's game of life and right now I'm trying to find neighbors(cells that are on top, to the bottom, and on the sides of the target cell). When I console log my function (basically to find the neighbors), I get values for the bottom and middle rows and all columns but for the top row I get "Cannot read property '-1' of undefined". Sometimes it will return "cannot read property of 'r' of defined" as well. I'm confused because I get return values when i console log both row (r) and columns (c). I'm also curious as to why I don't see this same error message when dealing with my columns. The messages on developer tools are very cryptic. I've spent quite a bit of time trying to figure this out but I'm truly stuck. Any help would be much appreciated.
I tried to do a JSbins: https://jsbin.com/bapazem/edit?html,css,js,output but its not liking the construction of my react components. You can see these areas clearly on my codepen: http://codepen.io/tbraden30/pen/AXgVNQ. Just click the play button and dev tools
Thanks in advance for your help
function randomGrid() {
var gridHeight = 20,
gridWidth = 20,
gridContainer = [];
for (var r = 0; r < gridWidth; r++) {
var row = [];
for (var c = 0; c < gridHeight; c++) {
row.push({
alive: Math.random() < 0.2,
neighbors: 0,
r: r,
c: c,
coords: [r, c]
});
}
gridContainer.push(row)
}
return gridContainer;
}
function isWithinBounds(cell) {
if (cell.r >= 0 && cell.r < 20 && cell.c >= 0 && cell.c < 20) {
return true
}
}
var grid = randomGrid();
var Board = React.createClass({
getInitialState: function() {
return {
cellLocation: randomGrid()
};
},
updateCells: function(r, c) {
var grid = this.state.cellLocation;
for (var r = 0; r < 20; r++) {
for (var c = 0; c < 20; c++) {
var cell = grid[r][c];
//console.log('cell', cell)
cell.neighbors = 0;
var isAlive = cell.alive;
var bottomLeft = grid[r + 1][c - 1],
bottomMiddle = grid[r + 1][c],
bottomRight = grid[r + 1][c + 1],
middleLeft = grid[r][c - 1],
middleRight = grid[r][c + 1],
topLeft = grid[r - 1][c - 1], **//problematic**
topMiddle = grid[r - 1][c], **//problematic**
topRight = grid[r - 1][c + 1];**//problematic**
/* if (isWithinBounds(bottomLeft) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(bottomMiddle) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(bottomRight) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(middleLeft) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(middleRight) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(topLeft) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(topMiddle) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(topRight) && isAlive) {
cell.neighbors++;
}*/
console.log('TR', topRight)
}
}
return cell;
},
render: function() {
return (
<div className='container grid_body'>
<CellMatrix grid={this.state.cellLocation}/>
<button type='button' onClick={this.updateCells} className='play'>Play</button>
</div>
)
}
}, this)
var CellMatrix = React.createClass({ //cells conglomerated into a grid
render: function() {
var fillCells = [],
grid = this.props.grid,
grid = grid.reduce((a, b) => a.concat(b)) //flattens the array.
grid.map(function(cellObject, index) {
fillCells.push(<Cell alive={cellObject.alive} r={cellObject.r} c={cellObject.c} coords={cellObject.coords} index={index} neighbors={this.updateCells}/>)
// console.log('fillcells', fillCells)
}, this)
return (
<div>
{fillCells}
</div>
)
}
})
var Cell = React.createClass({ //individual cell
render: function() {
return (
<td className={this.props.alive}
index={this.props.index}
coords={this.props.coords}
r={this.props.r}
c={this.props.neighbors}
neighbors={this.props.neighbors}
>
{this.props.children}
</td>
)
}
})
ReactDOM.render(<Board/>, document.getElementById('content'))
it sounds like an off by 1 error. when you generate the grid, you go from index 0..19, yet in the updateCells function you have a loop that sets c = 0, then subtracting 1 from it, meaning youre trying to access grid[-1][-1] when r and/or c is 0 (probably not what youre trying to do). then the fatal error likely occurs when r is 19 and c is 0, and you add one to r and subtract 1 from c. you end up accessing grid[20][-1] and since grid[20] is undefined, you get the error Cannot read property '-1' of undefined
I am using a Ext.picker.Month.
Setting maxDate does not disable dates which are grater than the maxDate value, but causes a validation error when selecting one.
How can I disable all future dates?
See fiddle -
1. Set maxDate to new Date()
2. Use ExtJS 4.2
You are instantiating a MonthPicker, not a DatePicker, yet you are using dozens of config options that are only available for a DatePicker.
You can see here how to instantiate a MonthPicker. As you can see there and especially in the docs, MonthPicker does not provide a config option to disable anything. Also, if you check the DatePicker behaviour, you see that disabledDates option does not change anything in MonthPicker, only AFTER the month has been selected, all days in the DatePicker are disabled.
So you would be on your own in implementing disabledDates for the MonthPicker, which I would do by looking at the code from DatePicker and MonthPicker, and trying to transfer.
Try this one...working on ExtJS 6.0.0.
You need to override 'Ext.picker.Month'
find attached image
Accepted values -
new RegExp('(?:)'); disable all month/year
new RegExp('^((?!^Apr/2016$|^May/2016$|^Jun/2016$|^Jul/2016$).)*$') disable all values other than Apr/May/Jun/Jul 2016
CSS -
.x-monthpicker-disabled {
background-color: #eee !important;
cursor: default !important;
color: #bbb !important;
}
disabledCls: Ext.baseCSSPrefix + 'monthpicker-disabled',
disabledMonthYearsRE: null,
disabledMonthYearsText: 'Disabled',
updateBody: function () {
//default Extjs code
if (me.rendered) {
//default Extjs code
//remove disabled cls and tooltip
years.removeCls(disabledCls);
months.set({
'data-qtip': ''
});
years.set({
'data-qtip': ''
});
months.removeCls(disabledCls);
//default Extjs code
if (dmyMatch) {
if (month == null && year == null) {
months.set({
'data-qtip': dmyText
});
months.addCls(disabledCls);
}
yrInView = false;
for (y = 0; y < yLen; y++) {
yr = yearNumbers[y];
el = Ext.fly(yearItems[y]);
if (dmyMatch.toString().indexOf(yr) == -1) {
el.dom.setAttribute('data-qtip', dmyText);
el.addCls(disabledCls);
}
if (yr == year) {
yrInView = true;
}
}
if (year != null && yrInView) {
for (m = 0; m < mLen; m++) {
mNo = m;
if (mNo < monthOffset) {
mNo = mNo * 2;
} else {
mNo = (mNo - monthOffset) * 2 + 1;
}
mt = months.elements[mNo];
if (dmyMatch.test(mt.text + "/" + year)) {
mt.setAttribute('data-qtip', dmyText);
mt.className = disabledCls + ' ' + mt.className;
}
}
} else {
//Add tooltip 'disabled'
months.set({
'data-qtip': dmyText
});
months.addCls(disabledCls);
}
}
}
},
//Disable month and year click for disabled values
onMonthClick: function (target, isDouble) {
var me = this;
if (!me.disabled && !Ext.fly(target).hasCls(me.disabledCls)) {
//default Extjs code
}
},
onYearClick: function (target, isDouble) {
var me = this;
if (!me.disabled && !Ext.fly(target).hasCls(me.disabledCls)) {
//default Extjs code
}
}