Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 How do I create a nested structure?

I have a set of expressions, and a ConditionSet when you select that one there will be create a new Expression line this one is nested. I created this as object object:

export class Expression {
    selector: string;
    constraint: string;
    value: string;
    children: Expression[];
}

So when this ConditionSet is selected I want to "move" or duplicate this to Expression.children. Now if I console.log this.expressions by adding one it looks as following:

enter image description here

But like you see the middle select box is nested and the arrivalDate has to be nested in the conditionSet.children like this:

Expression { 
selector: "conditionSet",
value:"" 
children: 
          selector:"ArrivalDate", 
          value:"" 
 }

And the nested addButton also have to push it to the .children to create the nested content.

I was thinking in this way but this does not work :(:

if(this.expression.selector === 'conditionSet'){
            this.prototypes = this.prototypes.children;
            console.log(this.prototypes);
        }

Can somebody help me out on this, I am really getting desperate on this issue.

Here is a PLUNKER

like image 883
Sireini Avatar asked Nov 09 '22 16:11

Sireini


1 Answers

In fact you don't have the addExpression method defined into your ExpressionComponent class, only in the ExpressionBuilderComponent one. So you can only add expression for the first level...

Moreover I think that you don't manage correctly the recursive aspect of your data.

For the ExpressionBuilderComponent component, you need to provide the expresion.children array for the expressions parameter of the expression component:

<expression *ngFor="#expression of expressions" [prototypes]="prototypes" [expression]="expression" [expressions]="expression.children"></expression>
<button class="btn btn-primary" (click)="addExpression()">Add Expression</button>

The same must be done for the ExpressionComponent itself:

<div class="col-xs-3">
  <select class="form-control" [(ngModel)]="selectedPrototypeSelector" (ngModelChange)="onPrototypeChange()">
    <option *ngFor="#p of prototypes" [value]="p.selector">
      {{ p.selectorName }}
    </option>
  </select>
</div>

<div *ngIf="prototype?.valueType === 'Set'">
  <div [ngClass]="{'nested-expression': prototype?.valueType === 'Set'}">
    <expression *ngFor="#expression of expressions" [prototypes]="prototypes" [expression]="expression" [expressions]="expression.children"></expression>
    <button class="btn btn-primary" (click)="addExpression()">Add Expression</button>
   </div>
 </div>

See this plunkr: https://plnkr.co/edit/zGcoZD?p=preview.

Edit

Regarding deletion, you need to handle a custom event (@Ouput) to do that since you need to remove the element from the children of the parent:

<div class="col-xs-1">
  <button class="btn btn-danger pull-right" (click)="deleteExpression()">Delete</button>
</div>

<div *ngIf="prototype?.valueType === 'Set'">
  <div [ngClass]="{'nested-expression': prototype?.valueType === 'Set'}">
    <expression *ngFor="#expression of expressions"
            [prototypes]="prototypes"
            [expression]="expression"
            [expressions]="expression.children"
            (expressionDeleted)="onExpressionDeleted(expression)">
    </expression>
    <button class="btn btn-primary" (click)="addExpression()">Add Expression</button>
  </div>
  <div>{{expression | json}}</div>
</div>

and in the component:

export class ExpressionComponent implements OnInit {
  (...)
  @Output() expressionDeleted: EventEmitter = new EventEmitter;

  (...)

  deleteExpression() {
    this.expressionDeleted.emit();
  }

  onExpressionDeleted(expression) {
    var index = this.expressions.indexOf(this.expression);
    this.expressions.splice(index, 1);
    console.log(index);
  }
}

See this plunkr for deletion: https://plnkr.co/edit/rQCILc?p=preview.

like image 126
Thierry Templier Avatar answered Nov 15 '22 08:11

Thierry Templier