We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Multiselect dropdown in checkbox mode wrapper issue when inside an ejDialog

Greetings.

I had to implement a multiselect with checkbox inside my angular project. By looking at the relevant documentation I found this (page https://ej2.syncfusion.com/angular/documentation/multi-select/checkbox/):

@Component({
    selector: 'app-root',
    template: `<ejs-multiselect id='multiselectelement' [dataSource]='sportsData' [fields]='fields' [mode]='mode' [selectAllText]='selectAllText' showSelectAll=true [placeholder]='placeholder'></ejs-multiselect>`,
    providers: [CheckBoxSelectionService]
})

Of course I didn't want to manually create a new component to inject a new instance of CheckBoxSelectionService everytime I needed such element in my application.
At first, I tried to provide "CheckboxSelectionService" directly in the app.module as a singleton, but as expected that didn't work.

So I though about it and tried to come up with a wrapper component which I can use as if it was your component and which takes care of providing a specific instance of CheckBoxSelectionService every time I make use of it. See the attached code with the wrapper.

I use it this way:

        <app-multiselect class="e-input mr-sm-2" name="roles" [dataSource]="roles" [fields]="ddlFields"
         placeholder="Ruoli" required width="200" [(ngModel)]="selectedRoles"></app-multiselect>


First question: does this approach makes sense to you? I'm asking this because I'm still a newbie with angular and just wanted to be sure that this makes sense.

Second question: there's an issue when such wrapper is used inside an HIDDEN ejDialog. When I assign a value to "this.selectedRoles"  (which is the [(ngModel)] of the multiselect wrapper) by subscribing to the ActivatedRoute this exception occurs:

core.js:6014 ERROR TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at FormBase.updateRemainTemplate (ej2-dropdowns.es2015.js:7486)
    at FormBase.updateDelimView (ej2-dropdowns.es2015.js:7464)
    at FormBase.initialValueUpdate (ej2-dropdowns.es2015.js:6923)
    at FormBase.updateActionList (ej2-dropdowns.es2015.js:5128)
    at FormBase.onActionComplete (ej2-dropdowns.es2015.js:5092)
    at FormBase.<anonymous> (ej2-dropdowns.es2015.js:565)
    at FormBase.push../node_modules/@syncfusion/ej2-angular-base/src/component-base.js.ComponentBase.trigger (component-base.js:209)
    at FormBase.<anonymous> (ej2-dropdowns.es2015.js:562)
    at FormBase.push../node_modules/@syncfusion/ej2-angular-base/src/component-base.js.ComponentBase.trigger (component-base.js:209)
    at FormBase.setListData (ej2-dropdowns.es2015.js:527)

by commenting such line of code the exception doesn't occur but of course I need to assign such data to the multiselect wrapper.
Below you can find all the relevant code of the wrapper multiselect inside the ejDialog:

COMPONENT:
<div #container></div>
<ejs-dialog #ejDialog [target]="container" visible="false">
 <ng-template #header>
      <span>{{operation}}</span>
  </ng-template>
  <ng-template #content>
    <form class="form-inline" #f="ngForm">
        <input class="e-input form-control mr-sm-2" name="username" [(ngModel)]="user.username" placeholder="Username" required type="text"/>
        <app-multiselect class="e-input mr-sm-2" name="roles" [dataSource]="roles" [fields]="ddlFields"
         placeholder="Ruoli" required width="200" [(ngModel)]="selectedRoles"></app-multiselect>
    </form>
  </ng-template>
</ejs-dialog>



CODE-BEHIND:
import { ComponentOnInitViewChildElementRefAfterViewInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { ActivatedRouteRouter } from '@angular/router';
import { UserForEdit } from '../../_models/userForEdit';
import { RoleForList } from '../../_models/roleForList';
import { UsersService } from '../../_services/users.service';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
import { EmitType } from '@syncfusion/ej2-base';

@Component({
  selector: 'app-edit-utente',
  templateUrl: './edit-utente.component.html',
  styleUrls: ['./edit-utente.component.css']
})
export class EditUtenteComponent implements OnInit {
  @ViewChild('ejDialog', {static: false}) ejDialogDialogComponent;

  constructor(private actrActivatedRouteprivate userServUsersService,
              private routerRouterprivate routeActivatedRoute) { }

  operationstring;
  userUserForEdit;

  rolesRoleForList[];
  ddlFields = { text: 'name'value: 'id' };
  selectedRolesany;

  ngOnInit() {

    this.actr.data
      .subscribe((data: { res_dataany[] }) => {   
      this.user = data.res_data[0];
      this.roles = data.res_data[1as RoleForList[];

      this.operation = (this.user.id === 0) ? 'Aggiungi' : 'Modifica';

      //manual array assignment for your convenience so that you can test it:
      
      this.selectedRoles = [01]; //IF THIS LINE IS COMMENTED THE EXCEPTION DOESN'T OCCUR!

      });
  }
}


Thank you a lot!








Attachment: multiselectwrapper_762684b3.zip

4 Replies

CA Carlo December 2, 2019 02:51 PM UTC

I have to add 2 further info to the reported issue:

1) the problem also happens if I directly use your ejs-multiselect instead of my wrapper

2) sometimes this happens also if the dialog is always shown (I have configured it this way since the dialog is embedded in a specific component which is rendered when a particular route is activated, and in that context the user expects the dialog to open). 

I think that the problem is caused by the fact that when the following instruction is executed:

this.selectedRoles = [01];

the multiselect dropdown sometimes has not been yet created (this always happens of course if the dialog is not shown). I say this because if I change the code in the following way, the problem doesn't happen:

<ejs-dialog #ejDialog [buttons]="dialogButtons" isModal="true" width="70%" (open)="afterDialogOpen($event)">

(added listener to dialog open event)

and then in the code-behind:


  ngOnInit() {
    this.actr.data
      .subscribe((data: { res_dataany[] }) => {
        this.user = data.res_data[0];
        this.roles = data.res_data[1as RoleForList[];

        this.operation = (this.user.id === 0) ? 'Aggiungi' : 'Modifica';

        this.tempSelectedRoles = [0, 1];
      });
  }

  afterDialogOpen(evt){
    //when the assignment is made, the multiselect is now rendered
    this.selectedRoles = this.tempSelectedRoles;
  }


Anyway, I see that this is just a workaround, so my questions remain:

1) does my wrapper make sense? even if the problem is also happening by directly using your multiselect component I'd still like your feedback on that

2) What's the correct way to use ngModel like [(ngModel)]="selectedRoles" in my multiselect wrapper when the multiselect wrapper is inside a dialog? There should be a cleaner way to achieve this..


SN Sevvandhi Nagulan Syncfusion Team December 3, 2019 09:41 AM UTC

Hi Carlo 

Greetings from Syncfusion support. 

Query 1: Of course I didn't want to manually create a new component to inject a new instance of CheckBoxSelectionService everytime I needed such element in my application. 
At first, I tried to provide "CheckboxSelectionService" directly in the app.module as a singleton, but as expected that didn't work. 
 
So I though about it and tried to come up with a wrapper component which I can use as if it was your component and which takes care of providing a specific instance of CheckBoxSelectionService every time I make use of it. See the attached code with the wrapper. 

We have checked the reported requirement. Since CheckBoxSelectionService module is injectable we have Injected the module in the MultiSelectAllModule. So you no need to provide the module at every time. You can import the MultiSelectAllModule from the dropdowns components. Please refer the below code snippet, 

[app.module.ts] 
 
import { MultiSelectAllModule } from '@syncfusion/ej2-angular-dropdowns'; 
 

Query 2: there's an issue when such wrapper is used inside an HIDDEN ejDialog. When I assign a value to "this.selectedRoles"  (which is the [(ngModel)] of the multiselect wrapper) by subscribing to the ActivatedRoute this exception occurs: 
 
We have placed the multiselect inside the EJSDialog as mentioned in the shared code snippet. In our end ngModel is working fine. Please refer the below code snippet for binding ngModel, 
 
[app.component.html] 
  <ejs-multiselect name="skillname" [(ngModel)]='value' [dataSource]='countries' [fields]='checkFields' [mode]='mode'> 
    </ejs-multiselect> 
 
[app.component.ts] 
 
ngOnInit(): void { 
        this.value=['AU','BM']; 
    } 
 
Also we suspect that duplicate modules were installed in your application. Generally duplicate package will be installed when there is any version mismatch between the packages. To resolve the reported issue in your end, kindly refer to the following UG documentation.  
  

 
Regards, 
Sevvandhi N 



CA Carlo replied to Sevvandhi Nagulan December 4, 2019 02:27 PM UTC


Your response to Query1We have checked the reported requirement. Since CheckBoxSelectionService module is injectable we have Injected the module in the MultiSelectAllModule. So you no need to provide the module at every time. You can import the MultiSelectAllModule from the dropdowns components. Please refer the below code snippet, 

Thanks. This fixed it. After including MultiSelectAllModule I didn't have to provide the CheckBoxSelectionService anymore, and so I could delete my now useless wrapper.

          Your response to Query2We have placed the multiselect inside the EJSDialog as mentioned in the shared code snippet. In our end ngModel is working fine. Please refer the below code snippet for binding ngModel, Also we suspect that duplicate modules were installed in your application. Generally duplicate package will be installed when there is any version mismatch between the packages. To resolve the reported issue in your end, kindly refer to the following UG documentation.  

I followed the suggested procedure to update modules and remove possible module duplicates. I also checked your sample, but after that I'm still experiencing this issue in my project. So, i prepared a sample for you to replicate the issue:

  • Just unzip it, give it a "npm install", and then "ng serve". 
  • Than go to address "http://localhost:4200/anag-utenti-dialog"
  •  Click a few times on an "edit" button of any row in the grid -> you will see that SOMETIMES (not always) when the dialog opens an exception is thrown and the multiselect becomes unusable.
The component with the relevant code is in src/app/routes/anag-utenti-dialog/anag-utenti/edit-utente/edit-utente.component.ts, lines 78 to 95. There you will see also a different version which is commented out but which is working (lines 97 to 118), but is much less cleaner: in that sample I have to copy the result provided by the observable in a temp variable and then, when the dialog open event triggers, I assign the value to the multiselect taking it from the temp variable. That doesn't seem to be a good way to fix that problem :(

So I'm asking you why the first version of the code, which seems to be much cleaner, sometimes throws the exception.

For your convenience, this is the exception:

core.js:6014 ERROR TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at FormBase.updateRemainTemplate (ej2-dropdowns.es2015.js:7493)
    at FormBase.updateDelimView (ej2-dropdowns.es2015.js:7471)
    at FormBase.initialValueUpdate (ej2-dropdowns.es2015.js:6930)
    at FormBase.updateActionList (ej2-dropdowns.es2015.js:5135)
    at FormBase.onActionComplete (ej2-dropdowns.es2015.js:5099)
    at FormBase. (ej2-dropdowns.es2015.js:565)
    at FormBase.push../node_modules/@syncfusion/ej2-angular-base/src/component-base.js.ComponentBase.trigger (component-base.js:209)
    at FormBase. (ej2-dropdowns.es2015.js:562)
    at FormBase.push../node_modules/@syncfusion/ej2-angular-base/src/component-base.js.ComponentBase.trigger (component-base.js:209)
    at FormBase.setListData (ej2-dropdowns.es2015.js:527)


Attachment: syncfusion_sample_f5c92162.7z


SN Sevvandhi Nagulan Syncfusion Team December 5, 2019 01:18 PM UTC

Hi Carlo, 
  
We have created an incident under your direct trac account. Please follow the incident for further assistance. 
  
Regards, 
Sevvandhi N 


Loader.
Live Chat Icon For mobile
Up arrow icon