如何拼接数组并更新组件视图

时间:2019-02-16 11:11:11

标签: nativescript angular2-nativescript nativescript-angular

Assalmualaikum .. 嗨,大家好。 我正在使用nativescript应用程序。但是我在childComponent上使用ngFor显示的splice数据数组之后,在更新视图上遇到问题。 问题仅在于splice。数组push运作良好。

父组件-> TambahTransaction

关于方法receiveQueue(args)

import { Component, OnInit, NgZone } from "@angular/core";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import * as app from "tns-core-modules/application";
import { Page } from "tns-core-modules/ui/page/page";
import { RouterExtensions } from "nativescript-angular/router";
import { TransactionService } from "~/app/shared/services/transaction.service";
import { BarcodeService } from "~/app/shared/services/barcode.service";
import { ActivatedRoute } from "@angular/router";
import { Transaction } from "~/app/shared/models/transaction.model";
import { GoodsTransaction } from "~/app/shared/models/goods-transaction.model";
import { ListGoods } from "~/app/shared/models/list-goods.model";
import { GoodService } from "~/app/shared/services/goods.service";
import { isAndroid } from "tns-core-modules/platform";
import { SearchBar } from "tns-core-modules/ui/search-bar";
import { GridLayout } from "ui/layouts/grid-layout";
import * as Toast from "nativescript-toast";
import { TextField } from "tns-core-modules/ui/text-field";

declare var android: any;

@Component({
  selector: "ns-tambah-transaction",
  templateUrl: "./tambah-transaction.component.html",
  styleUrls: ["./tambah-transaction.component.css"],
  moduleId: module.id
})
export class TambahTransactionComponent implements OnInit {
  statusKembalian = "Uang Kembali";
  isRegistering = false;
  isOkToSave = false;
  searchPhrase = "";
  barangQueue: Array<GoodsTransaction> = [];
  transaksi: Transaction = new Transaction();
  idToko = "";
  listGoodsView: Array<ListGoods> = [];
  listGoods: Array<ListGoods> = [];
  constructor(
    private page: Page,
    private routerExtensions: RouterExtensions,
    private transactionService: TransactionService,
    private barcodeService: BarcodeService,
    private activeRoute: ActivatedRoute,
    private goodService: GoodService,
    private ngZone: NgZone
  ) {
    this.idToko = this.activeRoute.snapshot.paramMap.get("id");
    this.transaksi.storeId = this.idToko;
    this.transaksi.total = 0;
    this.transaksi.createdAt = new Date();
    this.transaksi.payment = 0;
    this.transaksi.change = 0;
    this.transaksi.updatedAt = this.transaksi.createdAt;
    this.goodService.getListGoods(this.idToko).subscribe((data) => {
      this.listGoods = data;
      this.listGoodsView = this.listGoods;
    });
    this.page.on("loaded, propertyChange, change", (args) => {
      const window = app.android.startActivity.getWindow();
      window.setSoftInputMode(
        android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
      );
    });
  }

  ngOnInit() {}

  onDrawerButtonTap(): void {
    const sideDrawer = <RadSideDrawer>app.getRootView();
    sideDrawer.showDrawer();
  }
  onChangePayment(args) {
    const field = <TextField>args.object;
    const temp: any = <any>field.text;
    this.transaksi.payment = <number>temp;
    this.updateTotalBelanja();
  }
  receiveQueue(args) {
    const idxId = this.barangQueue.findIndex((element) => {
      return element.goodsId === args.id;
    });
    console.log("idxId : ", idxId);
    if (args.value === null) {
      this.barangQueue = this.barangQueue.splice(idxId, 1);
      console.log("daftar barang setelah dihapus 1");
      console.log(this.barangQueue);
      if (this.barangQueue.length > 0) {
        this.updateTotalBelanja();
      }
    } else {
      this.barangQueue[idxId] = args.value;
      this.updateTotalBelanja();
    }
  }
  updateTotalBelanja() {
    const temp = this.barangQueue.reduce((a, b) => {
      const t = new GoodsTransaction();
      t.totalAfterDisc = a.totalAfterDisc + b.totalAfterDisc;

      return t;
    });
    this.transaksi.total = temp.totalAfterDisc;
    this.transaksi.change = this.transaksi.total - this.transaksi.payment;
    if (this.transaksi.change > 0) {
      this.statusKembalian = "Hutang";
    } else {
      this.statusKembalian = "Uang Kembali";
    }
  }
  onCancel() {
    this.routerExtensions.back();
  }
  sBLoaded(args) {
    const searchbar: SearchBar = <SearchBar>args.object;
    if (isAndroid) {
      searchbar.android.clearFocus();
    }
  }
  onClear(args) {
    const searchBar = <SearchBar>args.object;
    searchBar.text = "";
    searchBar.dismissSoftInput();
  }
  onTextChanged(args) {
    const searchBar = <SearchBar>args.object;
    this.searchPhrase = searchBar.text;
    this.pencarian();
  }
  pencarian() {
    if (this.searchPhrase === "") {
      this.listGoodsView = this.listGoods;
    } else {
      this.listGoodsView = this.listGoods.filter((data) => {
        if (
          data.name.toLowerCase().includes(this.searchPhrase.toLowerCase()) ||
          data.barcode.includes(this.searchPhrase)
        ) {
          return data;
        }
      });
    }
  }
  onItemTap(args, item) {
    console.log("item tapped");
    console.log(item);
    const grid = <GridLayout>args.object;
    setTimeout(() => {
      grid.className = "list-group-item on-list-tapped";
    }, 0);
    setTimeout(() => {
      grid.className = "list-group-item";
    }, 150);

    const cekDuplicate = this.barangQueue.findIndex((element) => {
      return element.goodsId === item.id;
    });
    if (cekDuplicate === -1) {
      const queue = new GoodsTransaction();
      queue.goodsId = item.id;
      queue.barcode = item.barcode;
      queue.name = item.name;
      queue.sellingPrice = item.sellingPrice;
      queue.quantity = 1;
      queue.discOnSellingPrice = 0;
      queue.totalPrice =
        (queue.sellingPrice - queue.discOnSellingPrice) * queue.quantity;
      queue.discOntotalPrice = 0;
      queue.totalAfterDisc = queue.totalPrice - queue.discOntotalPrice;
      queue.createdAt = new Date();
      queue.updatedAt = queue.createdAt;
      this.barangQueue.push(queue);
    } else {
      this.barangQueue[cekDuplicate].quantity++;
      this.barangQueue[cekDuplicate].totalPrice =
        (this.barangQueue[cekDuplicate].sellingPrice -
          this.barangQueue[cekDuplicate].discOnSellingPrice) *
        this.barangQueue[cekDuplicate].quantity;
      this.barangQueue[cekDuplicate].totalAfterDisc =
        this.barangQueue[cekDuplicate].totalPrice -
        this.barangQueue[cekDuplicate].discOntotalPrice;
    }
    this.updateTotalBelanja();
    console.log("antrian barang");
    console.log(this.barangQueue);
    this.searchPhrase = "";
  }
  onItemLongPress(args, item) {
    const grid = <GridLayout>args.object;
    setTimeout(() => {
      grid.className = "list-group-item on-list-tapped";
    }, 0);
    setTimeout(() => {
      grid.className = "list-group-item";
    }, 100);
    this.routerExtensions.navigate([
      "goods/" + this.idToko + "/detailBarang",
      item.id
    ]);
  }

  onScan() {
    this.barcodeService
      .scanBarcode()
      .then((bar) => {
        console.log(bar, "ini bar");
        this.searchPhrase = bar;
        this.pencarian();
      })
      .catch((err) => {
        Toast.makeText(err).show();
      });
  }

  async onSave() {}
}

这是TambahTransaction的视图

<ActionBar class="action-bar" title="">
    <NavigationButton ios:visibility="collapsed" icon="res://menu" (tap)="onDrawerButtonTap()"></NavigationButton>
    <ActionItem icon="res://navigation/menu" android:visibility="collapsed" (tap)="onDrawerButtonTap()" ios.position="left">
    </ActionItem>
    <Label class="action-bar-title" text="Tambah Transaksi"></Label>
</ActionBar>
<DockLayout class="page page-content" stretchLastChild="true">
    <StackLayout dock="bottom">
        <ListView height="160" [items]="listGoodsView" class="list-group daftar-barangku" *ngIf="listGoods.length > 0 && searchPhrase!== ''">
            <ng-template let-dataitem="item" let-i="index">
                <GridLayout columns="*,2*,*" rows="*,*,*" class="list-group-item " (tap)="onItemTap($event, dataitem)"
                    (longPress)="onItemLongPress($event, dataitem)">
                    <Label [text]="dataitem.barcode" col="0" row="0" colSpan="2" textWrap="true" class="list-barcode"></Label>
                    <Label [text]="dataitem.name" col="0" row="1" colSpan="3" textWrap="true" class="list-nama-barang"></Label>
                    <Label [text]="dataitem.note" col="0" colspan="1" row="2" textWrap="true" class="list-note"></Label>
                    <Label [text]="'Rp. '+ dataitem.sellingPrice" col="2" row="2" textWrap="true" class="list-harga"></Label>
                </GridLayout>
            </ng-template>
        </ListView>
        <FlexboxLayout flexDirection="row" justifyContent="center">
            <SearchBar #pencarian hint="Cari Barang" (loaded)="sBLoaded($event)" [text]="searchPhrase" (textChange)="onTextChanged($event)"
                (clear)="onClear($event)"></SearchBar>
        </FlexboxLayout>
        <FlexboxLayout class="input-field" flexWrap="wrap" flexDirection="row" alignItems="center" justifyContent="space-between">
            <Button class="btn btn-warn" text="Cancel" (tap)="onCancel()" [isEnabled]="!isRegistering"></Button>
            <Button class="btn btn-warn" text="Scan" (tap)="onScan()" [isEnabled]="!isRegistering"></Button>
            <Button class="btn btn-primary" text="Save" (tap)="onSave()" [isEnabled]="!isRegistering && isOkToSave"></Button>
        </FlexboxLayout>
    </StackLayout>
    <ScrollView sdkExampleTitle sdkToggleNavButton>
        <StackLayout *ngIf="barangQueue.length > 0">
            <StackLayout *ngFor="let item of barangQueue">
                <Label [text]="item"></Label>
                <ns-daftar-transaction (queueEvent)="receiveQueue($event)" [queue]="item"></ns-daftar-transaction>
            </StackLayout>

            <GridLayout columns="*,2*,2*,2*" rows="*,*,*" class="list-transaction m-b-10 m-t-5">
                <Label text="Total Bayar" textWrap="true" col="1" colspan="2" row="0"></Label>
                <Label [text]="'Rp. '+transaksi.total" col="3" row="0"></Label>
                <Label text="Uang Pembayaran" textWrap="true" col="1" colspan="2" row="1"></Label>
                <TextField class="tf-uang-bayar" col="3" row="1" keyboardType="number" [text]="transaksi.payment"
                    (textChange)="onChangePayment($event)"></TextField>
                <Label [text]="statusKembalian" textWrap="true" col="1" colspan="2" row="2"></Label>
                <Label [text]="'Rp. '+transaksi.change" col="3" row="2"></Label>
            </GridLayout>
        </StackLayout>
    </ScrollView>
</DockLayout>

这是子组件-> DaftarTransaction

import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
import { GoodsTransaction } from "~/app/shared/models/goods-transaction.model";
import { Goods } from "~/app/shared/models/goods.model";
import { GoodService } from "~/app/shared/services/goods.service";
import { Button } from "tns-core-modules/ui/button";
import { TextField } from "tns-core-modules/ui/text-field";

@Component({
  selector: "ns-daftar-transaction",
  templateUrl: "./daftar-transaction.component.html",
  styleUrls: ["./daftar-transaction.component.css"],
  moduleId: module.id
})
export class DaftarTransactionComponent implements OnInit {
  dataBarang: Goods = null;
  @Input() queue: GoodsTransaction;
  @Output() queueEvent = new EventEmitter<{
    id: string;
    value: GoodsTransaction;
  }>();
  constructor(private goodService: GoodService) {}

  ngOnInit() {
    console.log("constructor daftar transaksi");
    console.log(this.queue);
    this.goodService
      .getGoods(this.queue.goodsId)
      .then((data) => {
        this.dataBarang = data;
      })
      .catch((err) => {
        console.log("gagal mendapatkan barang id : ", this.queue.goodsId);
        console.log(err);
      });
  }
  onChangePrice(args) {
    const btn = <Button>args.object;
    if (btn.className === "btn-ecer") {
      btn.className = "btn-grosir";
      this.queue.sellingPrice = this.dataBarang.sellingPriceGrosir;
    } else {
      btn.className = "btn-ecer";
      this.queue.sellingPrice = this.dataBarang.sellingPrice;
    }
    this.onUpdateQueue();
  }
  onDeleteQueue() {
    this.queue = null;
    this.queueEvent.emit({ id: this.queue.goodsId, value: this.queue });
  }
  onUpdateQueue() {
    this.queue.totalPrice =
      (this.queue.sellingPrice - this.queue.discOnSellingPrice) *
      this.queue.quantity;
    this.queue.totalAfterDisc =
      this.queue.totalPrice - this.queue.discOntotalPrice;
    this.queueEvent.emit({ id: this.queue.goodsId, value: this.queue });
  }

  onChangeDiscOnSellingPrice(args) {
    const field = <TextField>args.object;
    const temp: any = <any>field.text;
    this.queue.discOnSellingPrice = <number>temp;
    this.onUpdateQueue();
  }

  onChangeDiscOnTotalPrice(args) {
    const field = <TextField>args.object;
    const temp: any = <any>field.text;
    this.queue.discOntotalPrice = <number>temp;
    this.onUpdateQueue();
  }

  onChangeQuantity(args) {
    const field = <TextField>args.object;
    const temp: any = <any>field.text;
    this.queue.quantity = <number>temp;
    this.onUpdateQueue();
  }
}

这是DaftarTransaction的视图

<GridLayout columns="*,2*,2*,2*" rows="*,*,*,*,*" class="list-transaction">
    <Button text="x" col="3" row="0" class="btn btn-del-goods" horizontalAlignment="right" (tap)="onDeleteQueue()"></Button>
    <TextField [text]="queue.quantity" class="tf-quantity m-l-5" maxLength="3" col="0" row="1" keyboardType="number" (textChange)="onChangeQuantity($event)"></TextField>
    <Label [text]="queue.name" textWrap="true" col="1" colspan="2" row="1"></Label>
    <Label [text]="'Rp. '+queue.totalAfterDisc" col="3" row="1"></Label>
    <Button verticalAlignment="bottom" text="*" class="btn-ecer" col="0" row="2" (tap)="onChangePrice($event)"></Button>
    <Label [text]="'Rp. '+queue.sellingPrice" col="1" row="2"></Label>
    <Label [text]="'Rp. '+queue.totalPrice" col="2" row="2"></Label>
    <Label text="Diskon" col="0" row="3"></Label>
    <TextField class="tf-discount" col="1" row="3" keyboardType="number" (textChange)="onChangeDiscOnSellingPrice($event)"></TextField>
    <TextField class="tf-discount" col="2" row="3" keyboardType="number" (textChange)="onChangeDiscOnTotalPrice($event)"></TextField>
    <Label [text]="'Rp. '+ (queue.sellingPrice-queue.discOnSellingPrice)" col="1" row="4"></Label>
</GridLayout>

我做splice后遇到的错误是这样的:

idxId :  1
JS: ERROR TypeError: Cannot read property 'goodsId' of null
JS: ERROR CONTEXT {
JS:   "view": {
JS:     "def": {
JS:       "nodeFlags": 1,
JS:       "rootNodeFlags": 1,
JS:       "nodeMatchedQueries": 0,
JS:       "flags": 0,
JS:       "nodes": [
JS:         {
JS:           "nodeIndex": 0,
JS:           "parent": null,
JS:           "renderParent": null,
JS:           "bindingIndex": 0,
JS:           "outputIndex": 0,
JS:           "checkIndex": 0,
JS:           "flags": 1,
JS:           "childFlags": 1,
JS:           "directChildFlags": 1,
JS:           "childMatchedQueries": 0,
JS:           "matchedQueries": {},
JS:           "matchedQueryIds": 0,
JS:           "references": {},
JS:           "ngContentIndex": null,
JS:           "childCount": 11,
JS:           "bindings": [],
JS:           "bindingFlags": 0,
JS:           "outputs": [],
JS:           "element": {
JS:             "ns": "",
JS:             "name": "GridLayout",
JS:             "attrs": [
JS:               [
JS:                 "",
JS:                 "class",
JS:                 "list-transaction"
JS:               ],
JS:               [
JS:                 "",
JS:                 "columns",
JS:                 "*,2*,2*,2*"
JS:               ],
JS:               [...
JS: ERROR TypeError: Cannot read property 'quantity' of null
JS: ERROR CONTEXT {
JS:   "view": {
JS:     "def": {
JS:       "nodeFlags": 1,
JS:       "rootNodeFlags": 1,
JS:       "nodeMatchedQueries": 0,
JS:       "flags": 0,
JS:       "nodes": [
JS:         {
JS:           "nodeIndex": 0,
JS:           "parent": null,
JS:           "renderParent": null,
JS:           "bindingIndex": 0,
JS:           "outputIndex": 0,
JS:           "checkIndex": 0,
JS:           "flags": 1,
JS:           "childFlags": 1,
JS:           "directChildFlags": 1,
JS:           "childMatchedQueries": 0,
JS:           "matchedQueries": {},
JS:           "matchedQueryIds": 0,
JS:           "references": {},
JS:           "ngContentIndex": null,
JS:           "childCount": 11,
JS:           "bindings": [],
JS:           "bindingFlags": 0,
JS:           "outputs": [],
JS:           "element": {
JS:             "ns": "",
JS:             "name": "GridLayout",
JS:             "attrs": [
JS:               [
JS:                 "",
JS:                 "class",
JS:                 "list-transaction"
JS:               ],
JS:               [
JS:                 "",
JS:                 "columns",
JS:                 "*,2*,2*,2*"
JS:               ],
JS:               [...

大家有什么解决办法吗?

如果您对我使用的代码/逻辑提出建议,我将不胜感激。

0 个答案:

没有答案