Angular8拖放问题,涉及多种情况

时间:2019-08-21 11:08:28

标签: javascript angular angular8 angular-dragdrop

我正在使用Angular8拖放,遇到了一些问题

我的概念是什么,我在做什么

  1. 我拖放货物的卡车
  2. 我将包裹拖放到的包裹 一切正常

我正在使用下面的JSON数据结构(如下所示),该结构通过moveItemInArraytransferArrayItem函数进行了更新

trucks = [{
    "..": '',
    "Deliveries": [{
        "..": '',
        "Packages": [{

        }, {}, {}, ....]
    }, {}, {}, ....]
}, {}, {}, ....]

一切正常,但是我需要通过拖放操作应用一些额外的东西

  1. 我希望将包裹直接放入卡车中...因此,当包裹直接放入卡车中时,我想在该卡车的运送中添加一个运送对象,然后在该运送中,我要分配放置包

  2. 我希望将交货直接放置在交货范围内...因此,当直接下降交货时,我想将以前交货的所有包装都移至当前交货

我已经尝试了很多不同的方法,但是拖放操作会受到干扰并且错过了行为

下面是我的ts和HTML模板代码

import { Component, Input, OnInit } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';

import { ModelTruck } from '../../core/models/model-truck';
import { ModelDelivery } from '../../core/models/model-delivery';
import { ModelPackage } from '../../core/models/model-package';

@Component({
    selector: 'app-manual',
    templateUrl: './manual.component.html',
    styleUrls: ['./manual.component.css']
})

export class ManualComponent implements OnInit {

    @Input() packages: ModelPackage[];
    @Input() trucks: ModelTruck[];
    @Input() deliveries: ModelDelivery[];

    /**
     * Trucks inside work area
     */
    workTrucks = [];

    /**
     * Deliveries drop inside trucks connected element IDs
     */
    truckIds = ['no-trucks'];

    /**
     * Packages drop inside deliveries connected element IDs
     */
    deliveryIds = ['no-delivery'];

    /**
     * Column from which we are applying filter
     */
    column: any = 'Km';

    /**
     * Direction use for filter ASC or DESC
     */
    direction = 1;

    /**
     * Choosed truck/delivery/package data
     */
    choosed = {
        '1': '-',
        '2': '-',
        '3': '-',
        '4': '-',
        '5': '-',
        '6': '-',
        '7': '-',
        '8': '-',
        '9': '-',
        '10': '-',
        '11': '-',
        '12': '-',
        '13': '-',
        '14': '-',
        '15': '-',
        '16': '-',
        '17': '-',
        '18': '-',
        '19': '-',
        '20': '-',
        '..': '..',
    };

    /**
     * Initializing constructor
     */
    ngOnInit() {

        this._createConnectedIds();
        this._calculateAllStuff();
    }

    /**
     * Creating connected link Ids for the drag and drop elements
     */
    _createConnectedIds() {

        // For the deliveries to be drag and drop
        for (let truck of this.trucks) {
            this.truckIds.push(`truck-${truck.ID}`);
            for (let delivery of truck.Deliveries) {
                this.deliveryIds.push(`delivery-${delivery.ID}`);
            }
        }

        // For the packages to be drag and drop
        for (let delivery of this.deliveries) {
            this.deliveryIds.push(`delivery-${delivery.ID}`);
        }
    }

    /**
     * Onchange sort by
     */
    doSort(sort) {
        this.direction = sort == 'ASC' ? 1 : -1;
    }

    /**
     * Onchange filter by
     */
    doFilter(filter) {
        this.column = filter;
    }

    /**
     * Event on drop the packages
     */
    onPackageDrop(event: CdkDragDrop<string[]>) {

        if (event.previousContainer === event.container) {
            moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
        } else {
            transferArrayItem(event.previousContainer.data,
              event.container.data,
              event.previousIndex,
              event.currentIndex);
        }

        this._calculateAllStuff();
    }

    /**
     * Event on drop the deliveries
     */
    onDeliveryDrop(event: CdkDragDrop<string[]>) {

        if (event.previousContainer === event.container) {
            moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
        } else {
            transferArrayItem(event.previousContainer.data,
              event.container.data,
              event.previousIndex,
              event.currentIndex);
        }

        this._calculateAllStuff();
    }

    /**
     * Event on drop the trucks
     */
    onTruckDrop(event: CdkDragDrop<string[]>) {

        if (event.previousContainer === event.container) {
            moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
        } else {
            transferArrayItem(event.previousContainer.data,
              event.container.data,
              event.previousIndex,
              event.currentIndex);
        }

        this._calculateAllStuff();
    }

    /**
     * Calculate all the stuffs
     * Related to weight, volume, cost and number of packages etc
     */
    _calculateAllStuff() {

        this._removeDeliveriesWithoutPackage();
        this._calculateTrucksStuff();
        this._calculateDeliveriesStuff(this.deliveries);

        console.log('-----------------------');
        console.log('Trucks Inside The List');
        console.log(this.trucks);
        console.log('Trucks Inside Work Area');
        console.log(this.workTrucks);
    }

    /**
     * Remove deliveries without package
     */
    _removeDeliveriesWithoutPackage() {

        // Remove deliveries not contains package (Deliveries area)
        this.deliveries = (this.deliveries).filter(function(obj) {
            return obj.Packages.length != 0;
        });

        // Remove deliveries not contains package (Work Area)
        for( let truck of this.workTrucks ) {
            truck.Deliveries = (truck.Deliveries).filter(function(obj) {
                return obj.Packages.length != 0;
            });
        }
    }

    /**
     * Calculate package related stuffs
     * Related to weight, volume, cost and number of pieces etc
     */
    _calculatePackagesStuff(packages) {

        let packageStuffs = {
            ActualWeightDry: packages.filter((obj) => obj.TypePackage === 'dry').length,
            ActualWeightCold: packages.filter((obj) => obj.TypePackage === 'cold').length,
            ActualWeight: 0,
            ActualVolume: 0,
            ActualCostMerchandise: 0,
            NumberPackages: packages.length,
            NumberPieces: 0
        };

        for( let item of packages ) {
            packageStuffs.ActualWeight += item.ActualWeight;
            packageStuffs.ActualVolume += item.ActualVolume;
            packageStuffs.ActualCostMerchandise += item.ActualCostMerchandise;
            packageStuffs.NumberPieces += item.NumberPieces;
        }

        return packageStuffs;
    }

    /**
     * Calculate deliveries related stuffs
     * Related to weight, volume, cost and number of pieces etc
     */
    _calculateDeliveriesStuff(deliveries) {

        let deliveryStuffs = {
            MaxCostMerchadise: 0,
            ActualWeight: 0,
            ActualVolume: 0,
            NumberDestinations: deliveries.length,
            ActualCostMerchandise: 0,
            NumberPackages: 0,
            NumberPieces: 0,
            Trip: 0
        };

        for( let delivery of deliveries ) {
            deliveryStuffs.MaxCostMerchadise += delivery.MaxCostMerchadise;
            deliveryStuffs.ActualWeight += delivery.ActualWeight;
            deliveryStuffs.ActualVolume += delivery.ActualVolume;
            deliveryStuffs.ActualCostMerchandise += delivery.ActualCostMerchandise;
            deliveryStuffs.NumberPackages += delivery.Packages.length;
            deliveryStuffs.NumberPieces += delivery.NumberPieces;
            deliveryStuffs.Trip += delivery.Trip;

            let packageStuffs = this._calculatePackagesStuff(delivery.Packages);
            let keys = Object.keys(packageStuffs);
            for( let key of keys ) {
                delivery[key] = packageStuffs[key];
            }
        }

        return deliveryStuffs;
    }

    /**
     * Calculate trucks related stuffs for both work and in list
     * Related to weight, volume, cost and number of pieces etc
     */
    _calculateTrucksStuff() {
        this._calculateForTruck(this.trucks);
        this._calculateForTruck(this.workTrucks);
    }

    /**
     * Calculate truck stuff
     * Resulable code
     */
    _calculateForTruck(trucks) {
        for( let truck of trucks ) {
            let deliveryStuffs = this._calculateDeliveriesStuff(truck.Deliveries);
            let keys = Object.keys(deliveryStuffs);
            for( let key of keys ) {
                truck[key] = deliveryStuffs[key];
            }
        }
    }

    /**
     * Recalculating time
     */
    doRecalcTime() {
        alert('Doing recalculate time[need to implement]');
    }

    /**
     * Recalculating the order
     */
    doRecalcOrder() {
        alert('Doing recalculate order[need to implement]');
    }

    /**
     * Choosed element
     */
    choose(elem) {
        this.choosed = elem;
    }

    /**
     * Choosed element keys only
     */
    choosedKeys() {
        return Object.keys(this.choosed);
    }

    /**
     * Check if object
     */
    isItObject(elem) {
        return elem instanceof Object;
    }
}

<div class="main">
    <div class="width-20 truck-lists">
        <div class="sorting">
            <div class="sort-filters">
                <select (change)="doFilter($event.target.value)">
                    <option value="">Filter By</option>
                    <option value="TypeVehicle">TypeVehicle</option>
                    <option value="MaxWeight">MaxWeight</option>
                    <option value="MaxVolume">MaxVolume</option>
                    <option value="Km">Km</option>
                    <option value="Cost">Cost</option>
                </select>
            </div>
            <div class="asc-or-desc" (change)="doSort($event.target.value)">
                <select>
                    <option value="">Sort By</option>
                    <option value="ASC">ASC</option>
                    <option value="DESC">DESC</option>
                </select>
            </div>
        </div>
        <ul 
            cdkDropList 
            #truckArea="cdkDropList"
            [cdkDropListData]="trucks" 
            [cdkDropListConnectedTo]="[workArea]" 
            (cdkDropListDropped)="onTruckDrop($event)">
            <li 
                cdkDrag
                *ngFor="let truck of trucks | orderBy: {property: column, direction: direction}"
                class="truck-item"
                (click)="choose(truck)">
                <div class="truck-item-content">
                    {{ truck.TypeVehicle }} 
                    #{{ truck.ID }} | 
                    {{ truck.NumberDestinations }} Deliveries | 
                    {{ truck.NumberPackages }} Packages | 
                    {{ truck.Km }} Km | 
                    ${{ truck.Cost }}
                </div>

                <ol type="i">
                   <li *ngFor="let delivery of truck.Deliveries">
                       {{ delivery.State }}, {{ delivery.DestinationTR1 }}
                   </li>
                </ol>

                <span class="truck-size-tag">{{ truck.ID }}</span>
            </li>
        </ul>
    </div>
    <div class="width-60 truck-works">
        <div class="truck-works-dashboard">
            <ul 
                cdkDropList 
                #workArea="cdkDropList"
                [cdkDropListData]="workTrucks" 
                [cdkDropListConnectedTo]="[truckArea]"
                (cdkDropListDropped)="onTruckDrop($event)">
                <li 
                    cdkDrag
                    *ngFor="let truck of workTrucks"
                    class="truck-item truck-item-in-dashboard"
                    (click)="choose(truck)">
                    <div class="truck-item-content">
                        {{ truck.TypeVehicle }} 
                        #{{ truck.ID }} | 
                        {{ truck.NumberDestinations }} Deliveries | 
                        {{ truck.NumberPackages }} Packages | 
                        {{ truck.Km }} Km | 
                        ${{ truck.Cost }}
                    </div>
                    <div class="truck-row">
                        <div class="only-deliveries">
                            <ul 
                                cdkDropList 
                                [cdkDropListData]="truck.Deliveries" 
                                cdkDropListOrientation="horizontal" 
                                [cdkDropListConnectedTo]="truckIds" 
                                id="truck-{{ truck.ID }}" 
                                (cdkDropListDropped)="onDeliveryDrop($event)">
                                <li 
                                    cdkDrag
                                    *ngFor="let delivery of truck.Deliveries"
                                    class="delivery-item"
                                    (click)="$event.stopPropagation(); choose(delivery)">
                                    <div class="delivery-name">
                                        {{ delivery.State }} - {{ delivery.DestinationTR1 }}
                                    </div>
                                    <div class="delivery-time">
                                        {{ delivery.Delivery }}
                                    </div>
                                    <ul 
                                        cdkDropList 
                                        [cdkDropListData]="delivery.Packages" 
                                        [cdkDropListConnectedTo]="deliveryIds" 
                                        cdkDropListOrientation="horizontal"  
                                        (cdkDropListDropped)="onPackageDrop($event)" 
                                        id="delivery-{{ delivery.ID }}">
                                        <li 
                                            cdkDrag
                                            *ngFor="let package of delivery.Packages"
                                            [ngClass]="package.Type == 'Urgent' ? 'package-item urgent' : 'package-item'"
                                            (click)="$event.stopPropagation(); choose(package)">
                                            Pack #{{ package.ID }}<br>
                                            {{ package.Type }}
                                        </li>
                                    </ul>
                                </li>
                            </ul>
                        </div>
                        <div class="only-dashboard">
                            <table>
                                <thead>
                                    <tr>
                                        <th>Restriction</th>
                                        <th>Kg</th>
                                        <th>m3</th>
                                        <th>$</th>
                                        <th>Access</th>
                                        <th>Minutes</th>
                                        <th>Incomp</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <th>Actual</th>
                                        <td>{{ truck.ActualWeight }}</td>
                                        <td>{{ truck.ActualVolume }}</td>
                                        <td>${{ truck.ActualCostMerchandise }}</td>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                    </tr>
                                    <tr>
                                        <th>Max</th>
                                        <td>{{ truck.MaxWeight }}</td>
                                        <td>{{ truck.MaxVolume }}</td>
                                        <td>${{ truck.MaxCostMerchadise }}</td>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                    </tr>
                                    <tr>
                                        <th>Available</th>
                                        <td>
                                            {{ truck.MaxWeight - truck.ActualWeight }}
                                        </td>
                                        <td>
                                            {{ truck.MaxVolume - truck.ActualVolume }}
                                        </td>
                                        <td>
                                            ${{ truck.MaxCostMerchadise - truck.ActualCostMerchandise }}
                                        </td>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                    </tr>
                                    <tr>
                                        <th>%Available</th>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                        <td>-</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                    <span class="truck-size-tag">{{ truck.ID }}</span>
                </li>
            </ul>
        </div>
        <div class="no-truck-deliveries">
            <h4>No Truck</h4>
            <ul 
                cdkDropList 
                [cdkDropListData]="deliveries" 
                cdkDropListOrientation="horizontal" 
                [cdkDropListConnectedTo]="truckIds"
                (cdkDropListDropped)="onDeliveryDrop($event)" 
                id="no-trucks"
                class="no-truck">
                <li 
                    cdkDrag
                    *ngFor="let delivery of deliveries"
                    class="delivery-item"
                    (click)="choose(delivery)">
                    <div class="delivery-name">
                        {{ delivery.State }} - {{ delivery.DestinationTR1 }}
                    </div>
                    <div class="delivery-time">
                        {{ delivery.Delivery }}
                    </div>
                    <ul 
                        cdkDropList 
                        [cdkDropListData]="delivery.Packages" 
                        [cdkDropListConnectedTo]="deliveryIds" 
                        cdkDropListOrientation="horizontal"  
                        (cdkDropListDropped)="onPackageDrop($event)" 
                        id="delivery-{{ delivery.ID }}">
                        <li 
                            cdkDrag
                            *ngFor="let package of delivery.Packages"
                            [ngClass]="package.Type == 'Urgent' ? 'package-item urgent' : 'package-item'"
                            (click)="$event.stopPropagation(); choose(package)">
                            Pack #{{ package.ID }}<br>
                            {{ package.Type }}
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
    <div class="width-20 truck-datas">
        <div class="action-buttons">
            <button class="btn">Import</button>
            <button class="btn">Export</button>
        </div>
        <div class="element-datasets">
            <table>
                <tr *ngFor="let key of choosedKeys()">
                    <th [hidden]="isItObject(choosed[key])">{{ key }}</th>
                    <td [hidden]="isItObject(choosed[key])">{{ choosed[key] }}</td>
                </tr>
            </table>
        </div>
        <div class="action-buttons">
            <button class="btn" (click)="doRecalcTime()">Recalculate Time</button>
            <button class="btn" (click)="doRecalcOrder()">Recalculate Order</button>
        </div>
    </div>
</div>

1 个答案:

答案 0 :(得分:0)

我认为您应该基于event.container.data的类型来实现上述方案。

对于 1。要直接放入卡车的包裹

使用伪代码:

if type of event.container.data === package and type of event.previousContainer is === truck

   Add package to delivery then add delivery to truck

对于2.交货交货

if type of event.container.data === delivery and type of event.previousContainer === delivery

   for each package from delivery add package to new delivery

好像您可以使用打字稿instanceof一样。 https://www.typescriptlang.org/docs/handbook/advanced-types.html#instanceof-type-guards