ng2-tree icon indicating copy to clipboard operation
ng2-tree copied to clipboard

Question only: Select nodes without selecting parents/childrens

Open normantimorehl opened this issue 5 years ago • 13 comments

Dear ng2-tree community,

I don't get it. I investigated the demos published in .

I want to have the behaviour that I can select any node (checkbox selection) without automatic selection of it's parent or childs. For example in demo:

"Directory/File structure" -> select "home"... -> "home" and all subnodes ("firstUser", "Documents", etc) are selected.

"Programming languages tree" (with custom template) -> select "Hand icons" -> NO other nodes are selected.

But I can't get the relevant difference for that. Both are using "settings". The second on has a custom ng-template in it. I am using a custom template also.

What have I to do, so that a checkbox selection does not select other nodes?

I would appriciate it if someone could explain me the difference in selection behaviour.

Kind regards Timo

normantimorehl avatar Jul 31 '18 13:07 normantimorehl

Hey @normantimorehl and community

I'm facing that same problem, could you or somebody solve that? Please, tell me how to get this behavior (check the selected checkbox whithout auto checking its parent/chidren)

Thanks

renatotozzi avatar Sep 14 '18 13:09 renatotozzi

Hi renatotozzi,

after reverse engineering I determined that the autocheck behaviour depends on the "id" property of treemodel items. If you don't define id's, the tree component can't autocheck other items because ha can't find a controller with getControllerById. But without having id's you have the same problem too: you can't use getControllerById.

I propose to define a simple boolean property, something like "autocheckChildren" which will control whether to autocheck or not.

Kind regards Norman

normantimorehl avatar Sep 14 '18 13:09 normantimorehl

Hello @normantimorehl

Yeah, I've made reverse engineering too and get the same conclusion.

But the fact is that I need to fill the id property because I have to use getControllerById function in order to add children in nodes.

This your propose to create a boolean setting "autocheckChildren" was a good idea, but need to be implemmented in component.

It's possible someone to do that?

renatotozzi avatar Sep 14 '18 13:09 renatotozzi

Hi renatotozzi,

it's quite easy:

Step1: Add property in "tree-internal.component.ts"

export class TreeInternalComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {
  @Input() public tree: Tree;

  @Input() public settings: TreeTypes.Ng2TreeSettings;

  @Input() public template: TemplateRef<any>;

  public autocheckChildren = false;
  public isSelected = false;
  public isRightMenuVisible = false;
  public isLeftMenuVisible = false;
  public isReadOnly = false;
  public controller: TreeController;

And modify "onNodeChecked()":

    public onNodeChecked(): void {
    if (!this.checkboxElementRef) {
      return;
    }

    this.checkboxElementRef.nativeElement.indeterminate = false;
    this.treeService.fireNodeChecked(this.tree);
	if (autocheckChildren) {
		this.executeOnChildController(controller => controller.check());
	}
    this.tree.checked = true;
  }

That's all to to the change on default behavior.

If you want to use that property from outside of the component you have to add this property in "tree.component.ts" (add property in template and add input property):

@Component({
  selector: 'tree',
  template: `<tree-internal #rootComponent [tree]="tree" [settings]="settings" [template]="template" [autocheckChildren]="autocheckChildren"></tree-internal>`,
  providers: [TreeService]
})
export class TreeComponent implements OnInit, OnChanges, OnDestroy {
  private static EMPTY_TREE: Tree = new Tree({ value: '' });

  /* tslint:disable:no-input-rename */
  @Input('tree') public treeModel: TreeTypes.TreeModel;
  /* tslint:enable:no-input-rename */

  @Input() public settings: TreeTypes.Ng2TreeSettings;
  
  @Input() public autocheckChildren: boolean = false;

  @Output() public nodeCreated: EventEmitter<any> = new EventEmitter();

Easy and risk free change ;-)

My code is only a proposal ;-) Better solutions are welcome.

Kind regards Norman

Edits: code quotes were wrong

normantimorehl avatar Sep 14 '18 13:09 normantimorehl

Wow!!! It works like a charm!!

very thanks @normantimorehl

renatotozzi avatar Sep 14 '18 18:09 renatotozzi

@renatotozzi @normantimorehl Thank you for the solution! Is there any way where we can override this behavior via the controller or via settings?

@rychkog Any other ideas?

Any help is appreciated! :)

akshaygolash avatar Oct 09 '18 19:10 akshaygolash

Hi @rychkog

I used it by that way. I customized the component so that ir only works selecting clicked checkbox, never select parents and children, so I don't need to configure via settings. But I would appreciate it too, because I could use the original component, without customizaton.

renatotozzi avatar Oct 10 '18 01:10 renatotozzi

@akshaygolash @renatotozzi The settings are part of the source code, if you want to change this behaviour via settings you have to customize the component too, it's not possible to have this behaviour with the original component.

But the changes which are necessary to have the possibility to set the behaviour via settings are not much.

All changes described above are necessary (the property and the change to onNodeChecked() ). I find the option to set this behaviour via HTML markup property useful, so I recommend the "tree.component.ts" too.

-> important: the "public autocheckChildren = false" in "tree-internal.component.ts" defines the default behaviour if nothing else is used/set to change this. If you want to change the default only set this variable to true.

To add the possibility to change this via settings just add it in the settings class in "tree.types.ts":

export class Ng2TreeSettings {
  /**
   * Indicates root visibility in the tree. When true - root is invisible.
   * @name Ng2TreeSettings#rootIsVisible
   * @type boolean
   */
  rootIsVisible? = true;
  autoSelectRoot? = false;
  autoCheckChildren? = false;
  showCheckboxes? = false;
  enableCheckboxes? = true;
}

And to get this work you have to change the place where the settings are used. In "tree-internal.component.ts" inbetween the ngOnInt() method add this line:

    this.settings = this.settings || new Ng2TreeSettings();
    this.isReadOnly = !get(this.settings, 'enableCheckboxes', true);

// add this line
this. autocheckChildren = get(this.settings, 'autoCheckChildren', this. autocheckChildren);

    if (this.tree.isRoot() && this.settings.rootIsVisible === false) {
      this.tree.disableCollapseOnInit();
    }

After that you have the possibility to define the autoCheck behaviour via settings.

For changing the controller you have to do additionally things. For example you have the possibility to extend the check() and the uncheck() methods. In this methods the controller uses the internal-tree-component instance do whatever you want then.

After all these things I think of create a folk of this project, what do you mean?

normantimorehl avatar Oct 10 '18 06:10 normantimorehl

@renatotozzi , @normantimorehl , Thanks alot for your response. I think it would be best to create a PR and get it in the original component so everyone can benefit from it. I do see this as a very common use case.

Let me know what you guys think?

akshaygolash avatar Oct 10 '18 16:10 akshaygolash

Hello @akshaygolash

I think so. How I said before, I'm using a custom version, but it would be better if I could use the original component, downloaded from npm.

However, I would like to remember that is important not auto check chidren and also parents. In my case, I want to check ONLY the clicked checkbox.

renatotozzi avatar Oct 10 '18 17:10 renatotozzi

@renatotozzi , That makes sense because you cannot expect a hybrid behavior from a tree. Either we have autoCheck both ways or make all nodes independent.

akshaygolash avatar Oct 10 '18 17:10 akshaygolash

Hey guys, youre all right, better is to include the enhancement in the main source code. But be realistic, there are much more important and critical issues like that: Issue 309: Not compatible with latest rjx

And the insight tab shows the frequency: only 22 commits the whole year 2018. The last one 2018-04. And if you are realistic: this projet is dead, sad but true.

normantimorehl avatar Oct 10 '18 18:10 normantimorehl

@normantimorehl @renatotozzi I am afraid that you may be right. I don't see any commits for past 6 months.

@rychkog Is there any plan to support this project?

akshaygolash avatar Oct 10 '18 18:10 akshaygolash