I am working with AG/IG ~12.3.
Users want to compare a list of scenarios with a dynamic length and several controls are necessary for each. The basics of it are the scenario type (to filter the list of scenarios down) and the scenarios list (for users to pick from). There is also a checkbox that, when checked, will also produce a start date dropdown for the scenario data.
Users will generally want to compare between 10 and 35 scenarios. The only thing I've found that comes close to adding these controls dynamically is this syncfusion article (with stackblitz example), but it's for Angular 8 and doesn't include multiple fields or how to handle the data within them.
I assume the methodology would utilize an object array similar to the below:
{ type:string, scenario:scenario, stitch:boolean, start:workweek }[]
I'm just unsure how to put it all together and have data actually work the way I expect.
I am using the input-group/dropdown method for creating the dropdown rather than the combo/singleSelection method and my basic input group looks like the below (taken from a component with 2 static input groups):
<div class="controls"> <igx-input-group #s1TypeGroup [igxToggleAction]="s1TypeDd" displayDensity="compact"> <igx-prefix style="width: 90px;"> Is Type: </igx-prefix> <input #s1TypeInput style="width: 65px;" type="text" igxInput [igxDropDownItemNavigation]="s1TypeDd" readonly="true" [(ngModel)]="scenario1Type" [value]="s1TypeDd.selectedItem?.value" (keydown.ArrowDown)="openDropDown('s1Type')" /> <igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple> <igx-icon>arrow_drop{{ s1TypeDd.collapsed ? '_down' : '_up' }}</igx-icon> </igx-suffix> </igx-input-group> <igx-drop-down #s1TypeDd displayDensity="compact" (selectionChanging)="filterScenarios($event, 1)"> <div class="scrollable"> <igx-drop-down-item [selected]="true" [value]="'ALL'">ALL</igx-drop-down-item> <igx-drop-down-item *ngFor="let type of scenarioTypes" [value]="type.name">{{type.name}}</igx-drop-down-item> </div> </igx-drop-down> <igx-input-group #scenario1Group [igxToggleAction]="scenario1Dd" displayDensity="compact"> <igx-prefix style="width: 100px;"> Is Scenario: </igx-prefix> <input #scenario1Input style="width: 210px;" type="text" igxInput [igxDropDownItemNavigation]="scenario1Dd" readonly="true" placeholder="Later Horizon Start" [value]="scenario1Dd.selectedItem?.value" (keydown.ArrowDown)="openDropDown('scenario1')" /> <igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple> <igx-icon>arrow_drop{{ scenario1Dd.collapsed ? '_down' : '_up' }}</igx-icon> </igx-suffix> </igx-input-group> <igx-drop-down #scenario1Dd displayDensity="compact" (selectionChanging)="setScenario($event, 1)"> <div class="scrollable"> <igx-drop-down-item [selected]="true" [value]="">Choose a Scenario</igx-drop-down-item> <igx-drop-down-item *ngFor="let scen of scenario1List" [value]="scen.name">{{scen.name}}</igx-drop-down-item> </div> </igx-drop-down> <igx-checkbox [(ngModel)]="scenario1Stitch" (click)="match(1)">Stitch</igx-checkbox> <div class="controls" *ngIf="scenarioWorkweeks !== undefined && scenarioWorkweeks !== [] && actualWorkweeks !== undefined && actualWorkweeks !== [] && actualStartWw !== undefined && actualStartWw !== dummyWw && scen2StartWw !== undefined && scen2StartWw !== dummyWw && endWw !== undefined && endWw !== dummyWw && scenario1 !== undefined && scenario1.name !== scenario2.name && scenario1Stitch"> <igx-input-group #scen1StartGroup [igxToggleAction]="scen1StartDd" displayDensity="compact"> <igx-prefix style="width: 87px;"> Is Start:</igx-prefix> <input #scen1StartInput style="width: 55px;" type="text" igxInput [igxDropDownItemNavigation]="scen1StartDd" readonly="true" [(ngModel)]="scen1StartWw.name" placeholder="Is Scen Start WW..." [value]="scen1StartDd.selectedItem?.value" (keydown.ArrowDown)="openDropDown('scen1Start')"/> <igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple> <igx-icon>arrow_drop{{ scen1StartDd.collapsed ? '_down' : '_up' }}</igx-icon> </igx-suffix> </igx-input-group> <igx-drop-down #scen1StartDd displayDensity="compact" (selectionChanging)="setValue($event, 'scen1Start')"> <div class="scrollable"> <igx-drop-down-item *ngFor="let ww of scenarioWorkweeks | slice:scen1Span.start:scen1Span.end" [selected]="ww.name === scen1StartWw.name" [value]="ww.name">{{ww.name}}</igx-drop-down-item> </div> </igx-drop-down> </div> </div>
"Controls" refers to keeping these items inline, as each control group should be to reduce real estate waste:
.controls { display: inline-flex; width: 100%; }
setScenario/setValue (scenario/start dropdowns) is merely allocating the value of the dropdown changed to a parameter in the component for further processing.
match (checkbox) checks if the other scenario is the same and accordingly sets both checkboxes to the new selection.
My main concern is that I'm using @ViewChild for each dropdown as a means for accessing their values and unsure how to do so dynamically for an unknown number of each dropdown. The Type dropdowns can all be populated from the same list. The Scenario dropdowns can all be populated from a single list. Even the Start dropdown can be populated from a single list (using the slice pipe in my example). Without being able to access that data, though, I cannot produce the data grid and charts associated with the selections.
I think a basic example showing the first dropdown as a filter to the second and a final output that shows the chosen Type and Scenario (name) at the end would give me what I need.
For reference, the Scenario object has a name, type, start, end, and audit info (user created, created date, last user modified, last modified date) and IDs for everything (unnecessary for example). The Type object is just a name and ID. The workweek object includes a name, week number, year, month, quarter, and time period (ex: 04/03/2022 00:00:0000-04/09/2022 23:59:9999) with ID.
Thanks in advance.
Hello Chris,
Thank you for posting to Infragistics Community!
Reading your description, it seems quite a lot is going on in terms of user requirements, specific data models, exact data types and even layout. Business logic can be complex enough and very specific from application to application. Consequently, when providing support services, we try to concentrate on guidance to working with Infragistics controls and their functionalities and APIs, so that they can be leveraged by the developer to implement their own business logic.
Additionally, I would like to mention that Infragistics is not related to syncfusion components and cannot commit to being compatible with or similar to them.
I would also like to add that it is possible that I have not completely caught all aspects of your requirements regarding the dropdowns’ usage, as I am afraid the list is quite long. I may have to ask you for additional details in order to provide you with a more helpful sample. Thank you for understanding.
Having this in mind, I will try to address your specific question about dynamic addition of dropdown components. The dropdown items’ data model would be irrelevant for the purposes of the example.
Firstly, I created this sample with Ignite UI for Angular 12.3, which quite replicates the setup in the one referenced by you. What I can say is that the ViewChildren property decorator can be used to query the dynamically added controls. However, please, keep in mind that this is more of a general Angular topic, rather than particularly linked to Infragistics controls.
Any of the dropdowns' selected item can be accessed and the corresponding data item can be extracted from a collection, for example if there is an ID field. Please, refer to the logs in the onClick event in the sample.
In conclusion, please check out the referenced sample. In case you require further assistance with the dropdown component’s usage, please provide additional details about which specific part of the dropdown has to be configured. I recommend also referring to the IgxDropDownComponent public API for version 12.3 here and IgxDropDownItemComponent here.
If you need assistance of a certain aspect of the sample, do not hesitate to fork and modify it, by including only the relevant code and optionally adding comments.
Best regards,Bozhidara PachilovaAssociate Software Developer
I realize SyncFusion is a completely different product. As I mentioned, it was the only reference to what I'm attempting to do that I could find.
I also mentioned it was incomplete for what I need, as I need to replicate multiple dropdowns and access the data from all of them at once for further processing.
I have modified your example with data and logic that matches the requirement for individual rows. Without static references, it just replicates 2 instances of the scenarios dropdown and with static references, all filters are the same, so all lists are the same between replicated instances.
I'm not sure what the best path forward is.
Thank you for modifying the sample.
As far as I was able to understand the required functionality, you would like to still render multiple couples of dropdowns, where in each couple the first serves as a “filter” to the second, is this correct?
Looking at the modified sample, I can see that the issue is that firstl, both dropdowns currently have the same ids (#dropdown) and second, the filtering logic applies to all “scenarios” dropdowns, because of the way the items are populated.
If I am properly following this, I can say that the couple of dropdowns is a perfect candidate for its own component. Please, take a look at this modified sample and let me know if this resembles the target behavior.
Thank you for your cooperation. Looking forward to hearing from you.
Best regards, Bozhidara Pachilova
Yes, that's the direction I was headed, but I'm not able to get the data in the "dropdown-sample" component. I have modified the sample again to emulate the final state I'm looking for.
For whatever reason, the $event object is not propagating in the Scenario dropdown handler (selectionChanging) and so data is not persisting back to "dropdown-sample" for display in the basic table I've created there (should it propagate). It wasn't working with ViewChildren and QuerySelector, so I changed it to what I have been instructed to use in every other case with similar lack of affect.
I would appreciate more guidance in this matter.
Hi Chris,
Thank you again for modifying the sample and providing additional details!
There are few things I noticed that may cause issues.
The first is the difference in the template variable names of the two dropdowns (#typeDd and #scenarioDd) and the query string that configures the ViewChild decorator (‘type’ and ‘scenario’). The latter should match the template reference variable name. For more information, please refer to the official Angular documentation here. Although the queried components are not currently used in the sample code, this may result in undefined/null values in the further implementation.
Secondly, the reason that the event data is not propagating to the ‘scenario’ event handler is that the $event object should be passed to it, rather than a variable name, such as ‘scenario’:
<app-two-dropdowns [index]="num" (scenario)="updateScenarios($event)" ></app-two-dropdowns>
For your convenience, here is the updated sample. One thing you will notice is that configuring the scenarios array in the DropDownSample4Component has been transformed to an async operation, as well as that change detection is triggered after filtering the “scenList” in TwoDropdownsComponent. This is needed to work around Angular’s “Expression has changed after it was checked” error. For more details, I recommend referring to the documentation here.
I hope that this achieves the target functionality. Let me know if I may be of any further assistance.
Thanks for your help.
I have further updated the sample to include cleanly deleting scenarios without breaking order/losing numbers.
I believe any number of controls should be able to be added with ease, should they be necessary. I have also added a checkbox to my local project and it seems to be working as expected.
I am glad that you find my suggestions helpful.
Thank you for using Infragistics components.