-1

I have a case where I have a parent component and 2 child component (selection components based on ng-select) The idea is that when I select and item in the first ng-select, the same should be disabled in the 2nd. And vice versa.

In the parent I am using @ViewChildren to query the component and the set disabled input property

In the children I am emitting the information I need in the parent when I choose and item in the ng-select

In this method I am then finding the correct child component and setting the disabled input property

const connectionSelector = this.connectionSelectors.find(connectionSelector => connectionSelector.source == false);
connectionSelector.disabledConnection = this.selectedSourceConnection;

In the child component I have ngOnChanges method to check for the changes but the disabledConnection property does not get updated

It only works when I make a page load I am both emitting the changes to the parent on OnInit and when I change the item in the ng-select so the changes are emitted to the parent

Parent view:

<sc-connection-selector [default]="false" [source]="true" [quick]="false"
      [selectedConnection]="selectedSourceConnection"
      [disabledConnectionId]="disabledTargetConnectionId"
      (dataToEmit)="onValueChanged($event)">
</sc-connection-selector>

Child:

<ng-select [items]="connections" bindLabel="userName"
    [placeholder]="'general.select-placeholder' | translate " 
    (change)="onConnectionChange()" 
    groupBy="type"
    dropdownPosition="bottom" 
    [(ngModel)]="selectedConnection">
    <ng-template ng-optgroup-tmp let-item="item">
      <b>{{item.type || 'Unnamed group'}}</b>
    </ng-template>
  </ng-select>

What am I missing here ?

-Jani

jani_r
  • 637
  • 1
  • 7
  • 18

1 Answers1

1

Edit:

You are updating the value on the child component, no on the parent, OnChanges will trigger if

data-bound property of a directive changes

this means, that when the value on the parent component changes, it will trigger OnChanges on the child component.

For you to get the desired behavior, you should move the relevant section (where you update the disabled property) from the OnChanges function to the setter of disabledConnectionId, so every time that (disabledConnectionId) changes, you update the dropdown, here is the relevant code:

private currentDisabledConnectionId: Number;
@Input()
set disabledConnectionId(val: number) {
  if (this.currentDisabledConnectionId !== val) {
    this.currentDisabledConnectionId = val;
    this.setDisabledFields();
  }
}

private setDisabledFields() {
  this.connections.find(
    connection => connection.id == this.currentDisabledConnectionId
  ).disabled = true;
  console.log("connections: ", this.connections);
}

Notice I've changed the input to be a setter, and I saved the property as a private field.

Also note, what you posted on stackblitz doesn't remove previous disabled fields, only adds new ones (I suspect this is because you only pasted a reproduceable example).

Here is a working forked examlpe on stackBlitz

Moshezauros
  • 2,493
  • 1
  • 11
  • 15
  • I tried creating a new object with `Object.assign` but it's not working I also tried to change the Input to a number, that is basically all I need to be able to know which item to disable but that does not work either. If a update the field from the parent by querying the ViewChildren and setting the field this is only working on page load However if I set in the parent the field (which is then communicated to the child) it works but the problem is that in the child when I disable the item I don't for which ng-select the item should be disabled. They are using same the list of items. – jani_r Nov 30 '20 at 19:37
  • please add the html part to your question – Moshezauros Nov 30 '20 at 19:40
  • In the child component I then find the item which is sent from the parent and disable it in the list, like so: this.connections.find(connection => connection.id == changes['disabledConnectionId'].currentValue).disabled = true – jani_r Nov 30 '20 at 19:41
  • how are you passing the connectionSelector object from the parent to the children? – Moshezauros Nov 30 '20 at 20:00
  • did you notice disabledConnection (what you posted you set on the first function) is different than disabledTargetConnectionId which is what you pass to the child component? – Moshezauros Nov 30 '20 at 20:03
  • I am not passing that from parent to child. That is the ViewChildren list of connection selector. There are 2, source and target. I am querying those in the parent – jani_r Nov 30 '20 at 20:04
  • The property on the child component is now called disabledConnectionId and then in the parent I set it to disabledTargetConnectionId in the source connector and in target I set the disabledSourceConnectionId. This is so I know which one to disable, before I sent the whole object but I only need the id – jani_r Nov 30 '20 at 20:12
  • Ok, I can't help without seeing all of the code (and maybe even then), if you could recreate on stackblitz it would be best – Moshezauros Nov 30 '20 at 20:24
  • Here is the stackblitz, https://stackblitz.com/edit/angular-ivy-fwxqqs?file=src/app/connection-selector.component.ts. For some reason I can't get the ng-select styles applied. The disabled property in the connection object is set but it's not reflected in the ng-select. Maybe because of the styles. However this works in my local project. Maybe I went about this the wrong way. The problem is that in the components I only have 1 connection list but it needs to be different for the source and target, since the disabled connection can be different. Maybe I need to pass that in as well ? – jani_r Dec 01 '20 at 19:55
  • You also need to do this so that ng-select updates the items (mentioned in the docs):`this.connections = [...this.connections];` – jani_r Dec 03 '20 at 16:10