8

次のような従業員クラスがあるとします。

export class Employee {

    jobTitle: string;
    firstName: string;
    lastName: string;

    boss: Employee;
    workers: Employee[];

    constructor(jobTitle: string, firstName: string, lastName: string){
        this.jobTitle = jobTitle;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public addWorker(worker: Employee){
        this.wokers.push(worker);
        worker.boss = this;
    }

}

Employee次のようなイニシャルがあるとします。

function getInitialStaff(): Employee {

    let headWaiter: Employee = new Employee( "Head Waiter", "Sarah", "Hilton" );
    headWaiter.addWorker(new Employee("Bus Boy", "Joe", "BeefEater"));
    headWaiter.addWorker(new Employee("Waiter", "Randy", "Rainman"));

    let headCheif: Employee = new Employee( "Head Cheif", "Phil", "Yorstomux" );
    headWaiter.addWorker(new Employee("Dishwasher", "Andy", "Shark"));

    let owner: Employee = new Employee( "Owner", "Boris", "Laughington" );
    owner.addWorker(headWaiter);
    owner.addWorker(headCheif);
    return owner;
}

また、従業員が雇用または解雇されることもあると想定できます。これに沿った何か:

window.setTimeout(()=>{
    let someEmployee: Employee = /* Some existing employee */
    someEmployee.addWorker("someTitle", "someName", "someLastName");
}, someAmountOfTime);

PrimeNg ツリーに従業員を表示したい。

ツリー ウィジェットでは、表示されるデータが次のような treeNode インターフェイスに準拠している必要があります。

export interface TreeNode {
    label?: string;
    data?: any;
    icon?: any;
    expandedIcon?: any;
    collapsedIcon?: any;
    children?: TreeNode[];
    leaf?: boolean;
}

主な質問: Employee クラスを変更せずに、データを TreeNodes に変換する最良の方法は何ですか?


私が考えていること:

  • 新しい従業員を追加するときに、ツリーの状態 (開いているもの、選択されているものなど) を維持したい
  • 現在選択されている従業員を簡単に取得できる必要があります。
  • 2 つの重複したモデルを維持することを避けようとしています。
  • 合理的かつスケーラブルな方法で Angular2 の変更検出を利用したい

これは、現時点で私の EmployeeTree コンポーネントがどのように見えるかです:

@Component({
    selector: 'employee-tree',
    template: `
        <div>
            <p-tree>
                /* Open Question, I need to transform owner and then tie the resulting TreeNode to the tree */
            </p-tree>
        </div>
    `
    directives: [ Tree ]
})
export class EmployeeTree {
    @Input()
    private owner: Employee;
}

オプション 1 - Employee を TreeNode に変換するパイプを作成する

これにより、テンプレートは次のようになります。

<p-tree [value]="owner | convertToTreeNode"></p-tree>

そして、次のようなパイプを作成します。

@Pipe({name: 'convertToTreeNode'})
export class ToTreeNode implements PipeTransform {
    transform(employee: Employee): TreeNode {

        let treeNode: TreeNode = {
            label: employee.firstName + " " + employee.lastName,
            data: employee,
            children: []
        };

        employee.workers.forEach(worker => {
            treeNode.children.push(this.transform(worker));
        })

        return treeNode;

    }
}

長所短所:

  • これは角度の変更検出を利用します
  • これが純粋なパイプの場合、変更を見逃す可能性があります
  • これが不純なパイプの場合、重すぎる可能性があります
  • コンポーネントを非常にクリーンなままにし、責任をパイプに委任します
  • 新しいアイテムが追加されたときに、これが私の GUI 状態 (選択されているものと開いている/閉じているもの) を保持するかどうかわからない

オプション 2 - コンポーネント内でツリーの別の構造を維持する

@Component({
    selector: 'employee-tree',
    template: `
        <div>
            <p-tree [data]="employeeTree">
            </p-tree>
        </div>
    `
    directives: [ Tree ]
})
export class EmployeeTree {
    @Input()
    private owner: Employee;

    private employeeTree: TreeNode;

    // TODO - Somehow watch the owner for changes (how?) and then repopulate the employeeTree
}

従業員が変更されたときにトリクルアップするイベントを発行できると思います。これは私にフックする何かを与えることができます.


一般的に言えば、Angular2 を使用してこのようなことを行う最善の方法は何ですか。

要約すると、データを保存している形式とはわずかに異なる形式のデータを期待するウィジェットを使用したいと考えています。データをウィジェットにマッサージする標準的な angular2 の方法は何ですか? ここで私を助ける特別なangular2ソースはありますか? 2 つの別々のモデルを維持する必要がありますか? 私のツリーには数百または数千のアイテムが含まれる可能性があるため、パフォーマンスに多少の懸念があります。

4

2 に答える 2

0

Lodash mapを使用します。缶詰の例は次のとおりです。

import * as _ from 'lodash';
var users = [
  { 'user': 'barney' },
  { 'user': 'fred' }
];

// The `_.property` iteratee shorthand.
_.map(users, 'user');
// => ['barney', 'fred']

これが私のひねりです:

let emplData = [
         {  "jobTitle": "Paperboy",
            "firstName": "Fred",
            "lastName":  "Bloggs"
         },
         {  "jobTitle": "Tea boy",
            "firstName": "Charlie",
            "lastName":  "Creamslice"
         }         
    ]
   let resEl = document.getElementById("result");
   resEl.innerText =JSON.stringify(emplData.map(buildEmployeeNamesOnlyAndAddSeqNo));

    function buildEmployeeNamesOnlyAndAddSeqNo({firstName,lastName},index) {
       return {seqNo:index, firstName, lastName}
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.js"></script>

  <div id="result">
      
   </div>

于 2017-07-24T16:55:44.080 に答える