1

I have three Apis for categories,subcategories and policies.

For eg:

"https://restapi.com/project".

1.Category

In the case of category, I have to pass the body(raw data) as above json for the above Api

      {
        "startIndex":"1",
        "count":"150",
        "groupBy":"category",
        "searchTerm":"PROJECT:project1"
        }

Api Response: Listed out all categories

{ "data":
  [
   {
    projectName:null,
    categoryName: category1,
    subCategoryName:null,
    controlName:null
   },
   {
    projectName:null,
    categoryName: category2,
    subCategoryName:null,
    controlName:null
   }
  so on....
  ]
}

2.subCategory

In the case of sub-category, I have to pass the body(raw data) as above json for the above Api

      {
        "startIndex":"1",
        "count":"150",
        "groupBy":"subcategory",
        "searchTerm":"PROJECT:projectName1,CATEGORY: category1"
        }

Api Response: Listed out all subcategory of category1(because we give searchTerm by categoryName)

{ "data":
  [
   {
    projectName:null,
    categoryName: null,
    subCategoryName: subcategory1,
    controlName:null
   },
   {
    projectName:null,
    categoryName: null,
    subCategoryName: subcategory2,
    controlName:null
   }
  so on....
  ]
}

2.Control

In the case of control, I have to pass the body(raw data) as above json for the above Api

      {
        "startIndex":"1",
        "count":"150",
        "groupBy":"subcategory",
        "searchTerm":"PROJECT:projectName1,SUB-CATEGORY: subcategory1"
        }

Api Response: Listed out all Control of subcategory1(because we give searchTerm by subcategoryname)

{ "data":
  [
   {
    projectName:null,
    categoryName: null,
    subCategoryName: null,
    controlName: control1
   },
   {
    projectName:null,
    categoryName: null,
    subCategoryName: null,
    controlName: control2
   }
  so on....
  ]
}

When I open the 1st policy and after that, I open the next one. But the categories of second policy is automatically updated in first policy.

For calling these Apis, I used three get method for getCategory(),getSubcategory(),getControl().

I am attaching stackblitz example..

In stackBlitz I used three methods(like the method which I used)

ie,

open(i)====> I take index,i value for taking the policy values(but in my Api, I have to sent categoryName to get subcategory)

subOpen(i)====> I take index,j value for taking the subCategory values(but in my Api, I have to sent subCategory to get controls)

Here, https://stackblitz.com/edit/angular-9q4fbn?file=src%2Fapp%2Fapp.component.html.

Can you please tell me how to solve this??

Angel Reji
  • 533
  • 2
  • 11
  • 26

1 Answers1

0

Your data is already structured in a way that makes sense for binding it to your view. There's no need to micromanage references to parts of your data tree.

The logical issue you were having is that even though you were looping over categories in your tree, you were binding to the same reference of subCategories. Updating the reference to dropdownData1 or dropdownData2 changes the display for all categories.

It's actually much simpler to do what you want. Just use your existing data structure as it is.

https://stackblitz.com/edit/angular-dpziva

Here's the new view:

<ng-container *ngFor='let policy of dropdownData'>
  <tr>
    <td (click)="policy.expand = !policy.expand">
      <span class="{{policy.expand ?'fa fa-angle-down':'fa fa-angle-right'}}"></span>
      <span>{{policy.name}}</span>
    </td>
    <td class="text-center">
      <span class="label success">{{policy.policyName}}</span>
    </td>
  </tr>
  <ng-container *ngIf="policy.expand && policy.categories && policy.categories.length">
    <ng-container *ngFor='let category of policy.categories'>
      <tr>
        <td (click)="category.expand = !category.expand">
          <span style="margin-left: 20px;" class="{{category.expand ?'fa fa-angle-down':'fa fa-angle-right'}}"></span>
          <span>{{category.name}}</span>
        </td>
        <td class="text-center">
          <span class="label success">{{category.categoryName}}</span>
        </td>
      </tr>
      <ng-container *ngIf="category.expand && category.subCategories && category.subCategories.length">
        <ng-container *ngFor='let subcategory of category.subCategories'>
          <tr>
            <td (click)="subcategory.expand = !subcategory.expand">
              <span style="margin-left: 40px;" class="{{subcategory.expand ?'fa fa-angle-down':'fa fa-angle-right'}"></span>
              <span>{{subcategory.name}}</span>
            </td>
            <td class="text-center">
              <span class="label success">{{subcategory.subCategoryName}}</span>
            </td>
          </tr>
        </ng-container>
      </ng-container>
    </ng-container>
  </ng-container>
</ng-container>

Here's the new component class:

export class AppComponent {
  name = "Angular";
  dropdownData: any;

  data = {
    policy: [
      {
        policyName: "a1",
        name: "policy 1.1",
        expand: false,
        categories: [
          {
            categoryName: "c1",
            name: "category 1.1",
            expand: false,
            subCategories: [
              {
                subCategoryName: "s1",
                name: "subCategory 1.1"
              },
              {
                subCategoryName: "s2",
                name: "subCategory 1.2"
              }
            ]
          },
          {
            categoryName: "c2",
            name: "category 1.2",
            expand: false,
            subCategories: [
              {
                subCategoryName: "s5",
                name: "subCategory 2.1"
              },
              {
                subCategoryName: "s6",
                name: "subCategory 2.2"
              }
            ]
          }
        ]
      },
      {
        policyName: "a2",
        name: "policy 1.2",
        expand: false,
        categories: [
          {
            categoryName: "c4",
            name: "category 1.1",
            expand: false,
            subCategories: [
              {
                subCategoryName: "s13",
                name: "subCategory 1.1"
              }
            ]
          },
          {
            categoryName: "c5",
            name: "category 1.2",
            expand: false,
            subCategories: [
              {
                subCategoryName: "s17",
                name: "subCategory 2.1"
              },
              {
                subCategoryName: "s18",
                name: "subCategory 2.2"
              }
            ]
          },
          {
            categoryName: "c6",
            name: "category 1.3",
            expand: false,
            subCategories: [
              {
                subCategoryName: "s21",
                name: "subCategory 3.1"
              }
            ]
          }
        ]
      }
    ]
  };

  ngOnInit() {
    this.dropdownData = this.data.policy;
    console.log("dataas", this.dropdownData);
  }

  expand(collection, expandedItem) {
    collection.forEach(item => item.expand = item.id === expandedItem.id);
  }
}
Tom Faltesek
  • 2,768
  • 1
  • 19
  • 30
  • Tom I cant do this method.....the example which I gave is just an example... I already explain that I have the API. for each cases(policy,subcategory,category), I need to pass body... the response is also different.. So I need to use three get methods...getPolicy values are saved in a variable(dropdowndata),likewise getCategory(dropdowndata1), getSubcategory(dropdowndata2).. I cant reveal my Api right....Thats Y myself created the json structure and used three methods(to show u)...method which you shown me is not applicable in my case...Bcz I cant take subcategory from policy.subcategories. – Angel Reji Feb 07 '20 at 04:27
  • Ok. Perhaps if you provide an [example that illuminates the problem](https://stackoverflow.com/help/minimal-reproducible-example) you are having, then I can suggest a correction. It's difficult to make any valuable suggestions without a concrete replication of your issue. – Tom Faltesek Feb 07 '20 at 15:18
  • I would still suggest binding the entire tree to your view, as I've done in my example. If you need to load sections of that tree (categories/subcategories) when something is clicked, you can do so. Add data to your tree. Your error is binding the same reference to the categories for every policy. You must have separate references. – Tom Faltesek Feb 07 '20 at 15:27