【发布时间】:2021-09-05 06:26:43
【问题描述】:
我目前正在使用带有 Angular 的 Ionic 框架,我遇到了与“着色”相关的问题(因为缺乏更好的术语)我的应用程序开始屏幕中的这些小状态栏。
例子:
This is an example of the status bars working correctly
And this is what it looks like on page load, this is the problem
如图所示,我们有 5 个部门。如果部门完成了部分订单的工作,那么他们的小方块就会变成绿色。如果不是,则为红色。
作为参考,这是 HTML 的样子:
<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>
请原谅我的 CSS,这些天我将不得不将所有这些都转储到样式表中。
如您所见,它是一个包含所有订单的离子列表,由 orderResults 数组填充,该数组本身由 Observable 填充。通过对 Python API 的 HTTP 调用填充 Observable。
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';
}
}
至于 this.orderResults,它由 OrderService 服务填充。
像这样:
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);
}
现在我们已经了解了情况。
如何在每个离子项目上调用一个函数来为我的小状态方块着色?
或者,调用一个函数来检索所有元素并为它们着色?
或者,或者,在 ngOnInit 上为它们全部着色并过滤元素数组,仅显示那些需要使用 display:none; 看到的元素; (如果我能让它发挥作用,这可能是我最喜欢的方法。)
我尝试过的:
-
只需调用searchForLot()函数ngOnInit;
不顺利,我的 this.ordersElements = Array.from(document.getElementsByClassName('OrderItem'));变量将返回空值,因为列表中的 ion-item 尚未创建。
-
在我的 order.service.ts getOrders() 函数中添加 await/.promise();
没有做任何不同的事情。老实说,有点像冰雹玛丽。
-
使用生命周期钩子;
起初看起来很有希望,但与 ngOnInit 的问题相同,列表项最后加载,因为页面上的所有内容在 API 可以传递信息之前加载。
-
使用指令?和/或使用@ViewChildren/@ViewChild?;
非常神秘的文档,可能需要阅读更多关于它们的信息,找不到任何与我的用例相关的示例。
-
在我的 production.page.ts 中动态生成 HTML 元素;
这是我目前正在做的事情。
等等……我已经尝试了很多我只是想不起来了。
我想我会在 Stack Overflow 上发布这篇文章,并从比我更好的人那里获得一些反馈(第一个 angular/ionic 网站)。
欢迎任何反馈,完全改变我调用数据的方式是可能的,我之前曾与 ngOnInit 一起工作,但我决定不直接使用我的 Observable(使用 *ngFor="Let order of Observable 变量"),因为它导致 API 调用翻倍。所以我选择用 Observable 的数据填充一个数组,然后将它绑定到我的列表中,我们就在这里。
我宁愿一个完整的答案,而不仅仅是代码。我必须为正在进行的其他项目学习理论。
如果您需要更多信息,请告诉我。
感谢您的宝贵时间! 非常感谢。
【问题讨论】:
-
是否可以将您的代码复制到 Stackblitz 上?这可以通过使用 ViewChildren 而不是 getElementById 和 ngStyle/ngClass 来设置颜色等以更 Angular 的方式完成。:)
-
@LarsRodal 以前从未使用过 Stackblitz,但我可能可以用静态数据复制它。在我的午餐自动取款机上,大约一个小时后回来
-
不幸的是,Stackblitz 不起作用,由于某种原因,IDE 不明白
是什么,我怀疑他们可能使用的是旧版本的 Ionic。不过不确定。 -
那么您能为您的数据模型提供接口吗?我看到它们被设置为任何,知道这些会更容易给出解决方案????
-
添加了一个我认为应该对你有用的答案,我对你当前代码的理解:)
标签: angular typescript ionic-framework dom