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.