Components: Select-all toggle in tree example has the wrong state

Created on 26 Sep 2018  路  10Comments  路  Source: angular/components

Bug, feature request, or proposal:

Checkbox tree don't work properly (official documentation example) => https://material.angular.io/components/tree/examples

What is the expected behavior?

Se attached images, after click on parent childs are not selected

What is the current behavior?

1)
image

2)
image

3)
image

What are the steps to reproduce?

see my images and offical examples:
https://material.angular.io/components/tree/examples
or:
https://stackblitz.com/angular/gabkadkvybq?file=app%2Ftree-checklist-example.ts

Thanks and Regards

P2 docs help wanted

All 10 comments

I actually just had this brought to my attention by my team's QA. I have not yet been able to figure out how to get around this. My process to reproduce this bug is exactly the same as listed above.

Actually the problem is not the children selection, but the root internal handling:
image

As you can see in the above image, the properties indetermined and checked are set as false both on the root left on the initial situation (Reminders) and on the root on which I followed the steps on the initial post (Groceries).

The first root is both not-indefined and not-checked, but is displayed as checked,

I ran into the same issue a couple of days ago, I managed to find a solution.
On the checkboxes I suggest to bind the handler to the "click" event instead of the "change" .
First in the handler do event.preventDefault() so the internal state of the checkboxes won't change and it won't affect the visual state of the checkbox.
The handlers:

  1. For simple node, toggle it's state and then go over all his ancestors to the top and update the state by using the descendantsAllSelected and descendantsPartiallySelected for each ancestor.
  2. For parent node which contains children, instead of simple toggle
    "this.checklistSelection.toggle(node);"
    get it's new status by the data of it's descendants, as mentioned in section 1

More over, consider adding the mappers of simpleNode and flatNode inside the dataSource. It will save time and space instead of declaring those every time.

Found a solution:
in the component you have to define another method, say descendantsAllUnselected(node), similar to the existing descendantsAllSelected(node).

descendantsAllUnselected(node: TodoItemFlatNode): boolean { const descendants = this.treeControl.getDescendants(node); return descendants.every(child => !this.checklistSelection.isSelected(child)); }

In the HTML, change the [checked] property of the root checkbox to

[checked]="descendantsAllSelected(node) || !descendantsAllUnselected(node)".

Why? I don't know. But it works.

Probably there's a bug in the isSelected method of the SelectionModel class.

@bellons91, with your solution if you:

  1. expand "Groceries"
  2. check "Almond Meal flour"
  3. check "Groceries" => all "Groceries" childs become checked, but "Grocerie" becomes unchecked

@Nastia1409 This solved the issue for me. Thanks!

@ducalai damn, you are right! Thanks

I have found a solution, I will be creating a pull request shortly. It also solves your problem @ducalai

@fabioloreggian thanks for your solution! Almost done...

  1. Expand Groceries
  2. Check "Almond Meal flour"
  3. Check "Organic eggs"
  4. Check "Protein Powder"
  5. Check "Fruits"
    => "Groceries" becomes checked
  6. Uncheck "Groceries"

=> All children stay checked

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RoxKilly picture RoxKilly  路  3Comments

vanor89 picture vanor89  路  3Comments

kara picture kara  路  3Comments

savaryt picture savaryt  路  3Comments

julianobrasil picture julianobrasil  路  3Comments