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>
1
  • Can you create a plunker? Commented Nov 20, 2017 at 18:48

6 Answers 6

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

Sign up to request clarification or add additional context in comments.

1 Comment

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.
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.

Comments

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..>

1 Comment

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.
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.

4 Comments

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.
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.
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?
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.
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>

1 Comment

I get this error "AssetsComponent.ngfactory.js:253 ERROR TypeError: Cannot read property 'parent' of undefined"
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.

1 Comment

Wouldn't I then need to define myVariable for each element (in the component)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.