3

How do I access [attr.open]="false" from the div "child_div". In short I want to emulate the code sample below, but I don't know how to access parent attr from child div.

<div class="parent_div" *ngFor="let level_1 of [1,2,3]" [attr.open]="false">
   <div class="chlid_div" *ngIf="parent.attr.open">

       <div class="parent_div" *ngFor="let level_2 of [1,2,3]"
       [attr.open]="false">
          <div class="chlid_div" *ngIf="parent.attr.open">
             content
          </div>
       </div>

   </div>
</div>
yodalr
  • 9,778
  • 10
  • 32
  • 47

6 Answers6

1

You can make use of the Following Template

<div [attr.open]="my()">
   <div class="chlid_div" *ngIf="data">content</div>
</div>

Component

export class AppComponent {
  data: boolean;


  my() {
    this.data = true;
  }

}

Working Example

Rahul Singh
  • 19,030
  • 11
  • 64
  • 86
  • This would work, but it's not really referencing the parent div, as it's referencing a component variable. I will have many of those parent divs with child divs and I don't want to create multiple variables. – yodalr Nov 21 '17 at 13:40
1

Ok the solution was actually pretty simple, no directives or editing in component needed, pure template solution.

<div #areaLevel class="parent_div" *ngFor="let level_1 of [1,2,3]">
   <div class="chlid_div" [hidden]="areaLevel.expanded">

        <div class="button" [class.closed]="areaLevel.expanded" (click)="areaLevel.expanded = !areaLevel.expanded">
            +
        </div>

       <div #areaLevel class="parent_div" *ngFor="let level_2 of [1,2,3]">
          <div class="chlid_div" [hidden]="areaLevel.expanded">
             ...this can continue indefenitly...
          </div>
       </div>

   </div>
</div>

You can use either *ngIf or [hidden], like I did, but with *ngIf it destroys the DOM and if you open it again it builds it from 0.

yodalr
  • 9,778
  • 10
  • 32
  • 47
0

I didn't get what you wanted, don't you need an input and output to exchange a variable ?

I think you wanted to do something like this, don't you ?

<app-parent *ngIf="data">
  <app-child [myInput]="toChildren(value)" (toParent)="toParent(value)" 
       class="chlid_div">content</app..>
</app..>
andrea06590
  • 1,259
  • 3
  • 10
  • 22
  • I'm going to set the value of the parent div [attr.open] using a mouse click. The child div will get a state according to what state the parent div is. I don't want to create multiple value variables as I'll be using many instances of this div using *ngFor and inside that *ngFor will be additional *ngFor divs using same logic. – yodalr Nov 21 '17 at 13:37
0

You cannot refer to the child element inside of its own ngIf directive because, as the expression is being evaluated, that element doesn't exist yet. Therefore, it cannot be used to get its parent.

One way to refer to the parent div is with a template reference variable. However, if you try to use #parentDiv in ngIf as in the following example:

<div #parentDiv [attr.open]="true">
    <div class="chlid_div" *ngIf="parentDiv.getAttribute('open') === 'true'">content</div>
</div>

Angular will throw an ExpressionChangedAfterItHasBeenCheckedError (see this plunker). The explanation for that problem is given in this answer by AngularInDepth.com.

One way to avoid that problem is to refer to members of the component class inside of the ngIf directive, instead of trying to refer to the DOM elements.

ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • Both of the approaches solve the problem, but are workarounds which would complicate the overall goal. I'm going to have many div's using *ngFor and inside those div's I will have extra *ngFor divs. All of those individual divs need to reference their parent div to get their state. Both of the approaches you suggest would require for me to dynamically create many different #parentDiv variables (eg #parentDiv1_1, #parentDiv1_2...) or different someValue variables. While I only really need each divs parent state. – yodalr Nov 21 '17 at 13:29
  • I don't think that it is possible to refer to the parent element inside of the `ngIf` directive without a template variable. When the `ngIf` expression is being evaluated, the child doesn't exist yet, so you cannot use it to get its parent. – ConnorsFan Nov 21 '17 at 13:53
  • Alright. I'm thinking that I'll need to use subcomponents, so each child would be a subcomponent which can have it's own individual variables. Do you see any problems with that approach? – yodalr Nov 21 '17 at 14:04
  • As long as you refer to component members, I think it should work. The main problem in your initial approach was trying to refer to a DOM element that was not yet available. – ConnorsFan Nov 21 '17 at 14:14
0

You can try to using the following code:

<div class="parent_div" *ngFor="let level_1 of [1,2,3]" [attr.open]="false">
    <!-- You need the #child -->
    <div class="chlid_div" *ngIf="child.parent.attr.open" #child>

        <div class="parent_div" *ngFor="let level_2 of [1,2,3]" [attr.open]="false">
            <div class="chlid_div" *ngIf="parent.attr.open">
                content
            </div>
        </div>
    </div>
</div>
LordAlpaca
  • 166
  • 5
  • I get this error "AssetsComponent.ngfactory.js:253 ERROR TypeError: Cannot read property 'parent' of undefined" – yodalr Dec 29 '17 at 11:55
0

you can just bind them to the same variable in your component

<div class="parent_div" *ngFor="let level_1 of [1,2,3]" 
 [attr.open]="myVariable">
   <div class="chlid_div" *ngIf="myVariable">

Furthermore, each component each has it's own scope, so the variables will automatically be mapped to the correct parent.. In other words, if you have 10 of these on the page, the angular component is smart enough to know myVariable only applies to the scope of the 1 component and only the 1 component will be affected.

JBoothUA
  • 3,040
  • 3
  • 17
  • 46