Issue
I am currently using the Ionic framework with Angular, I am having an issue related to "coloring" (for a lack of better term) these little status bars that I have in my applications start screen.
Example:
This is an example of the status bars working correctly
And this is what it looks like on page load, this is the problem
We have 5 departments, as can be seen in the image. If the department is finished working on part of the order, then their little square will turn green. If not, it is red.
For reference, this is what the HTML looks like:
<ion-content>
<ion-list>
<div class="OrderItem" *ngFor="let order of orderResults">
<ion-item button id="{{ order.OrderID }}" [routerLink]="['order-details/', order.OrderID]">
<ion-label text-wrap>
<h1 class="OrderIdentifier" style="text-align: center;">{{ order.OrderID }}</h1>
<h3 style="text-align: center;">Lot: {{ order.productionLotNumber }} --- Stop: {{ order.StopNumber }}</h3>
<div style="display: inline-flex; margin-left: 25%; width: 50%;">
<p class="Desk" id="{{ order.DeskStatus }}" style="width: 20%;text-align: center;">Desk</p>
<p class="Cabinets" id="{{ order.CabinetStatus }}" style="width: 20%; text-align: center;">Cabinets</p>
<p class="Hutch" id="{{ order.HutchStatus }}" style="width: 20%;text-align: center;">Hutch</p>
<p class="Table" id="{{ order.TableStatus }}" style="width: 20%;text-align: center;">Table</p>
<p class="Wallunit" id="{{ order.WallunitStatus }}" style="width: 20%;text-align: center;">Wallunit</p>
</div>
</ion-label>
</ion-item>
</div>
</ion-list>
</ion-content>
Pardon my CSS, I will have to dump all that into a stylesheet one of these days.
As you can see, its an ion-list with all the orders, populated by the orderResults array, which that itself is populated by an Observable. The Observable being populated by an HTTP call to a Python API.
production.page.ts:
export class ProductionPage implements OnInit {
ordersElements: Array<any>;
lotResults: any;
orderResults: any;
constructor(private orderService: OrderService) { }
ngOnInit() {
this.orderService.getLots().subscribe(data =>
{
this.lotResults = data;
});
this.orderService.getOrders().subscribe(data => {
this.orderResults = data;
});
}
}
searchForLot() {
let tempOrderResults = this.orderResults;
this.ordersElements = Array.from(document.getElementsByClassName('OrderItem'));
this.searchLot = (document.getElementById('selectLot') as HTMLSelectElement).value;
this.searchOrder = parseInt((document.getElementById('inputOrder') as HTMLInputElement).value);
this.searchStop = parseInt((document.getElementById('inputStop') as HTMLInputElement).value);
if (!(this.searchLot === undefined) || !(isNaN(this.searchOrder)) || !(isNaN(this.searchStop))) {
if (this.searchLot === undefined) {
this.searchLot = '0';
}
if (isNaN(this.searchOrder) || (this.searchOrder.toString()).length > 6) {
this.searchOrder = 0;
}
if (isNaN(this.searchStop) || (this.searchStop.toString).length >= 3) {
this.searchStop = 0;
}
if (this.searchLot !== '0') {
tempOrderResults = tempOrderResults.filter(item => item.productionLotNumber === this.searchLot);
}
if (this.searchOrder !== 0) {
tempOrderResults = tempOrderResults.filter(item => item.OrderID === String(this.searchOrder));
}
if (this.searchStop !== 0) {
tempOrderResults = tempOrderResults.filter(item => item.StopNumber === this.searchStop);
}
const matches: Array<any> = [];
//For each Order that is left after the filters
tempOrderResults.forEach(result => {
//For each element's from the original API call (which are drawn)
this.ordersElements.forEach(orders => {
const divElement = (orders as HTMLDivElement);
//Hide all elements, easier to hide everything and selectively choose which elements to show in a different function
divElement.style.display = 'none';
if(result.OrderID === divElement.children[0].id) {
//Filling array with DOM elements that match filtered orders, by order identifier
matches.push(divElement);
}
});
});
//for each order, send div element to the function for proper "coloring"
matches.forEach(div => {
(div as HTMLDivElement).style.display = 'inline';
this.colorStatus(div);
});
}
}
colorStatus(statusElement) {
//This will have to be modified to take an element, then change that element status
//statusElement is the element object itself
const eDesk = (statusElement as HTMLDivElement).getElementsByClassName('Desk')[0];
const eCabinets = (statusElement as HTMLDivElement).getElementsByClassName('Cabinets')[0];
const eHutch = (statusElement as HTMLDivElement).getElementsByClassName('Hutch')[0];
const eTable = (statusElement as HTMLDivElement).getElementsByClassName('Table')[0];
const eWallunit = (statusElement as HTMLDivElement).getElementsByClassName('Wallunit')[0];
console.log(eDesk);
if(eDesk.id === '0')
{
(eDesk as HTMLParamElement).style.backgroundColor = 'Red';
} else {
(eDesk as HTMLParamElement).style.backgroundColor = 'Green';
}
if(eCabinets.id === '0')
{
(eCabinets as HTMLParamElement).style.backgroundColor = 'Red';
} else {
(eCabinets as HTMLParamElement).style.backgroundColor = 'Green';
}
if(eHutch.id === '0')
{
(eHutch as HTMLParamElement).style.backgroundColor = 'Red';
} else {
(eHutch as HTMLParamElement).style.backgroundColor = 'Green';
}
if(eHutch.id === '0')
{
(eTable as HTMLParamElement).style.backgroundColor = 'Red';
} else {
(eTable as HTMLParamElement).style.backgroundColor = 'Green';
}
if(eHutch.id === '0')
{
(eWallunit as HTMLParamElement).style.backgroundColor = 'Red';
} else {
(eWallunit as HTMLParamElement).style.backgroundColor = 'Green';
}
}
And as for this.orderResults, it is populated by the OrderService service.
Like so:
order.service.ts
@Injectable({
providedIn: 'root'
})
export class OrderService {
baseUrl = 'This is an ip, removed it for reasons, just imagine something like 192.168.***.***';
getOrders() {
const url = this.baseUrl + 'GetProductionOrders';
return this.http.get(url);
}
And now that we have the context on the situation.
How can I call a function on each ion-item, to color my little status squares?
or alternatively, call a function to retrieve all the elements and color them?
or or alternatively, color them all on ngOnInit and just filter the array of elements, displaying only those that need to be seen with display:none; (This is probably my favorite approach, if I could get it to work.)
What I have tried:
Just calling the searchForLot() function ngOnInit;
did not go well, my this.ordersElements = Array.from(document.getElementsByClassName('OrderItem')); variable will return nulls because the ion-item's inside the list have not been created yet.
Adding await/.promise() in my order.service.ts getOrders() function;
didn't do anything different. Honestly, kind of a hail mary.
Using Lifecycle hooks;
Seemed really promising at first, but same issue as ngOnInit, List items load last because everything on the page loads before the API can deliver the info.
Using directives? and/or using @ViewChildren/@ViewChild?;
Very cryptic documentation, would maybe need to read more about them, cant really find any examples that are related to my use case.
Dynamically generating the HTML elements in my production.page.ts;
This is what I am currently working on.
And etc... I have tried a lot more I just cant recall.
figured I'd post this on Stack Overflow and get some feedback from people who are much better at this than I am (first angular/ionic website).
Any feedback is welcome, completely changing how I call data is a possibility, I had this working with ngOnInit earlier but I decided against using my Observable directly (with *ngFor="Let order of Observable variable"), as it resulted in double the API calls. So I opted to populate an Array with the Observable's data and then bind that to my list, and here we are.
I'd rather a complete answer, not just code. I have to learn the theory for other projects in the works.
Let me know if you need any more information.
Thank you for the time! It is much appreciated.
Solution
Try using ngStyle. It has two types of syntaxes, for your usecase I think binding a single attribute ([style.attr]=value) is the simplest approach:
<div style="display: inline-flex; margin-left: 25%; width: 50%;">
<p class="Desk" [style.backgroundColor]="order?.deskStatus == '0' ? 'red' : 'green" id="{{ order.DeskStatus }}" style="width: 20%;text-align: center;">Desk</p>
<p class="Cabinets" [style.backgroundColor]="order?.CabinetStatus == '0' ? 'red' : 'green" id="{{ order.CabinetStatus }}" style="width: 20%; text-align: center;">Cabinets</p>
<p class="Hutch" [style.backgroundColor]="order?.HutchStatus == '0' ? 'red' : 'green" id="{{ order.HutchStatus }}" style="width: 20%;text-align: center;">Hutch</p>
<p class="Table" [style.backgroundColor]="order?.TableStatus == '0' ? 'red' : 'green" id="{{ order.TableStatus }}" style="width: 20%;text-align: center;">Table</p>
<p class="Wallunit" [style.backgroundColor]="order?.WallunitStatus == '0' ? 'red' : 'green" id="{{ order.WallunitStatus }}" style="width: 20%;text-align: center;">Wallunit</p>
</div>
If I understood correctly how your code is supposed the work, this should do the trick for you. :)
Answered By - Lars Rødal
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.