-
-
Notifications
You must be signed in to change notification settings - Fork 14
PolyLookup
PolyLookup is a multi-select control in Model Driven App. It allows users to select one or more items from a list of options.
PolyLookup control supports various types of relationships such as OOTB N-N relationship, custom N-N relationship, and N-N using Connection table.
![](https://private-user-images.githubusercontent.com/8686497/366180705-a995c95a-4c5f-4d19-9309-70d41819a8c7.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM2NjE4MDcwNS1hOTk1Yzk1YS00YzVmLTRkMTktOTMwOS03MGQ0MTgxOWE4YzcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NzY2NTI3MTI1YTk4MGYyNmI2MGNkZjVjZDczOTRhMmI2MmI5MTQ0MzNmOGQzNDIyMWM5N2E4M2E2NDcxYjc1MiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.6Zyx99SB4HPn6nE-KYu48TswDzQyzvdX2IUVkJFppMY)
- Supports various types of N-N relationships
- Clean design
- Minimal configuration
- Dynamic filtering
- Quick Create
- Optionally output selected as text
![](https://user-images.githubusercontent.com/8686497/231826928-11ad49bf-0312-49e4-a2d1-88353f5d9567.png)
Property | Usage | Type | Description |
---|---|---|---|
Bound Field* | bound | SingleLine.Text SingleLine.TextArea MultipleLine |
The field to host the control and output value |
Relationship Type* | input | Enum Many to many Custom N-N Connection
|
Relationship type between tables |
Relationship Name* | input | SingleLine.Text | - N-N: The relationship name to the associated table. - Custom N-N: The relationship name from the current table to the intermediate table. - Connection: Connected From relationship name |
Relationship 2 Name* (required for Custom N-N and Connection) | input | SingleLine.Text | - N-N: Not applicable. - Custom N-N: The relationship name from the intermediate table to the associated table. - Connection: Connected To relationship name |
Should Output Selected Text* | input | Enum Yes No
|
Whether the control should output selected items as text |
Output Selected Field (required if you want to use the control in Create form) | input | SingleLine.Text SingleLine.TextArea MultipleLine |
The field to output the selected records as a JSON array. Can be the same as "Bound Field" |
Lookup View | input | SingleLine.Text SingleLine.TextArea MultipleLine |
Lookup View configuration. Value can be a static text or bound to a field on the form, the value can be: 1. a FetchXML 2. a OData URL to a column of a record containing a FetchXML 3. An environment variable logical name containing a FetchXML 4. System View name |
Item Limit | input | Whole.None | Maximum number of selected items |
Show Icon | input | Enum None Use Entity Icon Use Record Image . Default: None
|
Whether to show an icon in option item. |
Allow Quick Create | input | Enum Yes No
|
Enable or disable the Quick Create button |
Tag Action | input | Enum None Open Inline Open Dialog Open Inline (intersect relationship) Open Dialog intersect relationship
|
Perform an action when a tag is clicked. Default: None |
Selected Item Template | input | SingleLine.Text | Dynamic template to display selected option text. Default to the first column in the lookup view if not provided. |
Show Option Details | input | Enum Collapsed Expanded Tooltip
|
Option to show more details in suggestion list. Default: Collapsed. |
Language Pack Path | input | SingleLine.Text | Path to a resx web resource, relative to the environment url (eg. /webresources/new_/resx/PolyLookup.1033.resx), to be used as Language Pack. Default to English if not provided. |
** is a required prop
Important
Please use the relationship name, not the relationship table name, see below samples
![](https://private-user-images.githubusercontent.com/8686497/279343247-78bf4ba6-14a1-43f8-a611-4e406086481c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzI3OTM0MzI0Ny03OGJmNGJhNi0xNGExLTQzZjgtYTYxMS00ZTQwNjA4NjQ4MWMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MTdhZjBlOTBlODA0ZWY1NjM5NzM2ZTI2ODUwZDIzNjJhYzQxMmUzYzJjZTAyNmQwMTlhNDA2MmUzN2JlZGVkZiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.D7hXdEocVpa7-P6gsR1Hz03hViglz7sXC0opJ6Us4qA)
![](https://private-user-images.githubusercontent.com/8686497/279343726-95525b27-6a6a-48f1-8306-6ee01d7fc60d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzI3OTM0MzcyNi05NTUyNWIyNy02YTZhLTQ4ZjEtODMwNi02ZWUwMWQ3ZmM2MGQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NGMzNGQ5MTVhYzgxNDE1MjhlMjRlNGQ3ZWZhMmNjZWUyYWZhZmVjMDZmNzUyNWZmNWVmZjIzYzU5N2IzM2JiOCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.tQrh1fWrkkVCHVw_ZCfaxCg3U4JNg8A1zCSprA7sVOs)
erDiagram
COURSE }o--o{ CATEGORY : relationship_1
erDiagram
STUDENT ||--o{ ENROLLMENT : relationship_1
CLASS ||--o{ ENROLLMENT : relationship_2
erDiagram
COURSE ||--o{ CONNECTION : course_connections1
COURSE ||--o{ CONNECTION : course_connections2
![](https://user-images.githubusercontent.com/8686497/222142259-1c6b9291-8201-499e-9f0c-1416f468fde2.png)
When user first clicks on the control and the search term is empty, it will load the first 50 records from the associated table.
The page size 50 is retrieved from the user's from personal settings.
![](https://user-images.githubusercontent.com/8686497/222157230-98d375d0-0d2b-4660-b50f-999f0f6b8bb0.png)
![](https://user-images.githubusercontent.com/8686497/222158545-85bd2d75-5517-4a59-a8ae-5e36d4a7ebae.png)
When search token {{PolyLookupSearch}}
is not present in Lookup View (see Dynamic Templating section below), the control will use default search by Primary Name attribute for records that start with the search term from the associated table. And wildcard search using *
is also supported by default in this case. For example, *ABC
will return records having the primary name contains ABC.
Note that Wildcard Search is not applied when Default Search is not used. This is to respect whatever filter condition operator that you specify in your FetchXML with the {{PolyLookupSearch}}
.
For example, given the below FetchXML which filters for active Course Categories
<fetch>
<entity name="storm_coursecategory">
<attribute name="storm_name"/>
<attribute name="storm_sortnumber"/>
<attribute name="storm_description"/>
<order attribute="storm_sortnumber" descending="false"/>
<filter type="and">
<condition attribute="statecode" operator="eq" value="0"/>
</filter>
</entity>
</fetch>
There is no {{PolyLookupSearch}}
token in the query. When user enters this search text *at*2
, the Default Search with wildcard search on the primary name attribute will be added and the query becomes like this
<fetch>
<entity name="storm_coursecategory">
<attribute name="storm_name"/>
<attribute name="storm_sortnumber"/>
<attribute name="storm_description"/>
<order attribute="storm_sortnumber" descending="false"/>
<filter type="and">
<condition attribute="statecode" operator="eq" value="0"/>
<condition attribute="storm_name" operator="like" value="%at%2%"/>
</filter>
</entity>
</fetch>
This will return all categories that contain at<any thing in between>2
![](https://private-user-images.githubusercontent.com/8686497/354844781-d6cfec35-445e-438a-a823-0db567488cf4.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NDg0NDc4MS1kNmNmZWMzNS00NDVlLTQzOGEtYTgyMy0wZGI1Njc0ODhjZjQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZWUwM2ZiMDIwMDczM2QxMWI2NjM3OTAyZDhmNjYxYWU1ODliNWExYjU0NmEyNzFmNDNkNzdiMjlkYzdhZTk4ZCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.UREkCRRN73d60CTFRpCvchENcwNdrHOgL-FkEFF4RHg)
In some cases, you may want to search on one or more columns other than the primary name, then you can pass a query like this
<fetch>
<entity name="storm_coursecategory">
<attribute name="storm_name"/>
<attribute name="storm_sortnumber"/>
<attribute name="storm_description"/>
<order attribute="storm_sortnumber" descending="false"/>
<filter type="and">
<condition attribute="statecode" operator="eq" value="0"/>
<condition attribute="storm_description" operator="like" value="%{{PolyLookupSearch}}%"/>
</filter>
</entity>
</fetch>
This will return all categories that have the description containing the search text. Primary name filter won't be added, and the *
wildcard won't apply in the search text. This can be improved in future releases.
There is a 100ms delay before the control starts searching.
![](https://user-images.githubusercontent.com/8686497/223473749-43e76637-5153-44a5-af84-41f716297a74.png)
The Quick Create button helps users quickly create a new option right in the current form without navigating away.
The Quick Create button can open the table's Quick Create Form, if "Allow Quick Create" is enabled in table settings and a Quick Create form is created and the Quick Create form is added to the model driven app
Important
An additional requirement for Quick Create Form to display is that there must be a lookup to the associated table and the lookup field is required. After you verified that the Quick Create Form is shown correctly by clicking the Quick Create button, you can safely delete the lookup field if you don't need it.
If "Allow Quick Create" table setting isn't enabled, the main form will be used as a dialog.
![](https://user-images.githubusercontent.com/8686497/225704562-48216dbe-67dd-4f1f-81ca-abaadfb5ae17.png)
Look View property is where you configure a custom query (FetchXML) which is used to retrieve including sort, filter, and display extended info in the suggestion items in the dropdown.
From v1.5.0, Lookup View becomes more powerful. Besides System View name, there are more ways to provide a FetchXML:
- Static FetchXML: FetchXML can be stored as text in the control property.
- OData URL: an OData URL to retrieve a single column that contains the FetchXML. For example,
/new_myconfigurations(00000000-0000-0000-0000-000000000001)/new_value
. See more here: https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/retrieve-entity-using-web-api#retrieve-a-single-property-value - Environment Variable: FetchXML can be stored in an environment variable. Learn more about environment variable here: https://learn.microsoft.com/en-us/power-apps/maker/data-platform/environmentvariables
- View Name: a system view name. Same as previous versions.
- Binding to a form field: This is useful when you want to construct a FetchXML with your own logic.
With this flexibility, you don't need to create empty System Views if you don't want to.
The control will determine the Lookup View Configuration based on the below flow:
flowchart TD
VALUE[LookupView value] --> IS_FETCH{contains < fetch>?}
IS_FETCH -->|Yes| FETCH[use value as is]
FETCH --> X
IS_FETCH -->|No| IS_ODATA{contains odata url?}
IS_ODATA -->|Yes| ODATA[use value returned from odata]
ODATA --> X
IS_ODATA -->|No| SEARCH_EV[search environment variable]
SEARCH_EV --> IS_EV{found?}
IS_EV -->|Yes| EV[use ev fetchxml]
EV --> X
IS_EV -->|No| SEARCH_VIEW[search view name]
SEARCH_VIEW --> IS_VIEW{found?}
IS_VIEW -->|Yes| VIEW[use view fetchxml]
VIEW --> X
IS_VIEW -->|No| DEFAULT[use default lookup view]
DEFAULT --> X(((End)))
you can pass a static FetchXML directly to the Lookup View property like this
![](https://private-user-images.githubusercontent.com/8686497/354846020-f6fa8598-5532-4ed9-8c49-6cc8f44c11c1.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NDg0NjAyMC1mNmZhODU5OC01NTMyLTRlZDktOGM0OS02Y2M4ZjQ0YzExYzEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MzllODBjNzg2ZWMyNTU4Mzg5ZjhkZjlkZjc0ODZkNmJiNTBiODYwN2FmYzBhODk4ZjgwOTE2YzU1Njg1YmY2YiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.ZMnUoTAlInQJh0RI9nDCcdRB9pf4wUBv0ofyG7HmORY)
![](https://private-user-images.githubusercontent.com/8686497/354846100-b1c44296-bbd1-4927-8688-9295cccac737.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NDg0NjEwMC1iMWM0NDI5Ni1iYmQxLTQ5MjctODY4OC05Mjk1Y2NjYWM3MzcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZGIyMzdkZDViYWE2ZGFmNWExYzAwMjVlMTI4ZDg4YzZlOGQ5MTM4OTlmNTY3ODU1NTJiODhiOGZjNGI4MGNkOSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.g2JiteDWEFstb3SUIXkeLQ-WgbaTlSh6YirZyaBl6v8)
Please note there is a maximum length depends on the type and form editor you choose:
Classic editor | Modern editor | |
---|---|---|
SingleLine.Text | 160 | 100 |
SingleLine.TextArea | 2052 | 2000 |
Multiple lines of text | 2052 | 1048576 |
You can store the FetchXML in any table column. And you can pass the query to the control using the single-property-value OData URL. For example, given a Custom Configuration table record to store the same static FetchXml above like this
![](https://private-user-images.githubusercontent.com/8686497/355172933-cb9df362-fea3-41e1-bc83-e9e79e3e0cb8.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE3MjkzMy1jYjlkZjM2Mi1mZWEzLTQxZTEtYmM4My1lOWU3OWUzZTBjYjgucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NDIzMDNlMGI2MjIwZThhOGY5MTI1MzE3ODVhMTQxNDk0ZmEzNTFkZGM5MTdlMDU1NzNhZDM3YjA5ZjY0MDA5YSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.NSnc-uxSKkErveEgsAZh6SStFjmR888oz6RAsBLy5sc)
The fetchXml is stored in the storm_value
field on the form. Then you can pass this query to the control like this
- full URL:
https://org941f632d.crm4.dynamics.com/api/data/v9.2/storm_customconfigurations(8F990A4A-4653-EF11-BFE3-000D3A445FE3)/storm_value
- relative URL:
/api/data/v9.2/storm_customconfigurations(8F990A4A-4653-EF11-BFE3-000D3A445FE3)/storm_value
- shorter relative URL:
/storm_customconfigurations(8F990A4A-4653-EF11-BFE3-000D3A445FE3)/storm_value
![](https://private-user-images.githubusercontent.com/8686497/355176469-642d256c-94dc-4adb-930a-b5fdba5fb74f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE3NjQ2OS02NDJkMjU2Yy05NGRjLTRhZGItOTMwYS1iNWZkYmE1ZmI3NGYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NzZmODhlZWUxNWI2YWE1Y2NhOWEwYTVjZGEzYzJmMjRmOGNhNjU5NGNkNzk2NjgwYzljZDIyN2Y4ZTI0YzNmNiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.08CbUg1TIh93pdSpqnB-8eYqEoY0BmOT0hFfqciedUo)
![](https://private-user-images.githubusercontent.com/8686497/355176903-7c450964-68f9-4856-86a9-2b6d20f75adf.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE3NjkwMy03YzQ1MDk2NC02OGY5LTQ4NTYtODZhOS0yYjZkMjBmNzVhZGYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NTk1YWZiYjMxYjVlNjc3Njk1NWUxZGEyMWE2MDgyNjUzZjFjNTZmMzg2ZGY1YTYyZmUzZjgxZTcwYzhkOWY3YiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.IkcVCNTK8fM6zVqK0iilcw7QlIVkHVBX1vantim6iek)
The FetchXML can be stored in an environment variable like this
![](https://private-user-images.githubusercontent.com/8686497/355177873-94d7d337-4f44-469e-b644-429fee1cfde7.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE3Nzg3My05NGQ3ZDMzNy00ZjQ0LTQ2OWUtYjY0NC00MjlmZWUxY2ZkZTcucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTQwOTg3NmVkZjFlMGM4NjZmNDc0OWM1MGZhNzUxMDlkMWEwZmM5M2FiYjVhMDM1ZDI2YTJjMWVkNDc3ZGYwYyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.x6Lf5qU-odM0ILzdiS4k8HgIgacbE0Vr8h9QmUBL5e0)
Then you can pass the query to the control using either the logical name or display name of the environment variable.
![](https://private-user-images.githubusercontent.com/8686497/355178961-a6f5f3a8-b308-4ed7-9451-394bbcbfa31f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE3ODk2MS1hNmY1ZjNhOC1iMzA4LTRlZDctOTQ1MS0zOTRiYmNiZmEzMWYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MjE2NDkxMDExZjYzYzhmMjljMWRhOWFmOTNkMTdmMGVhMzhlZTQzMGVlZGQ0NGRhZTZiOWU5NWFhN2VlMGY0YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.KPT-rzdHo0WNTc9PFKw3_svrffsNoBawYpFlmUqMuJw)
Note that the maximum length in Envrionment Variable is only 2000
You can create a normal system view using the view editor
![](https://private-user-images.githubusercontent.com/8686497/355179732-c1795f3a-7356-4d00-8b3d-bf0e0da1b212.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE3OTczMi1jMTc5NWYzYS03MzU2LTRkMDAtOGIzZC1iZjBlMGRhMWIyMTIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MGJiOThlODM1NjhiMmI0MWIyYmVkZmI2MjM1OTMzYjIwYjEyOTQ3YjllZDlmN2NlZjQ0YzRkMDlkNTI1Yzc2MSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.zm6lJ6Ks9J6ii40zMTre8B5vax-8i_6fWffvcGl5Jyw)
Then pass the view name to the control
![](https://private-user-images.githubusercontent.com/8686497/355181164-0ac71c93-49ce-48a8-b7b8-dae64f7cbdab.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTE4MTE2NC0wYWM3MWM5My00OWNlLTQ4YTgtYjdiOC1kYWU2NGY3Y2JkYWIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OGY4OWUxMjExNDY5YmM4NGFjMTkzNjI4MTc4ZmJkMDAwNjM2NmI3MmE5OTM3ZDk2YjIyMDI2OWU5ODQwYjNmYiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.6ft_i3W7ewmPs98PfIwzICbJ2KRXO_TRjRAa-Lh9RGc)
If the view is not found, the default system lookup view of the table will be used.
Note
Make sure you don't have two or more views with the same name.
✨ Binding lookup view configuration to a form field is like the "Infinity Gauntlet". You have all of the power from the above "gems", plus the ability to "react" to the field value changes.
That means when you bind the lookup view property to a field on the form. The field value will be used to determine the fetchxml to filter the dropdown options. When the field value changes, the filter will also be refreshed accordingly. The field value can be anything from the above options: your own custom fetchxml, odata URL, environment variable name, or a system view name. and of course, dynamic templating is supported in all options.
Now depending on how flexible your requirement is, you can update the bind field value with your logic, even mix and match the options, for example:
- populate bind field value with "view name 1" initially, when something happened on the form, set the value to "view name 2", etc..., or
- if (some condition), use "env variable 1", else if (some other condition), use "env variable 2", else use "view name 1", or
- use this
<fetch>...</fetch>
by default, if (some condition), update the fetch, else if (some condition), use "view name 1"
Note that you can use dynamic templating in all your fetchxml, doesn't matter where the fetch is stored. so you don't need to create new views/variables/fetch if it can be done using dynamic templating.
You can see the possibilities are endless. The only limitation is your imagination! ✨
Important
Lookup View may not work if it's too long/complex with lots of conditions. This is because the component is using the FetchXML in the Lookup View to retrieve data using Web API GET
method and the maximum length of the URL is about 8000 characters. But the fetchxml will need to be URL encoded, so we only have about 4600 characters maximum for the actual FetchXML. It should be enough in most cases.
![](https://user-images.githubusercontent.com/8686497/225707800-25fc41f0-3eee-41c3-b7a9-b3f7ef8226cc.png)
Another advanced feature is dynamic templating. This helps you to insert data from the current record into your lookup field.
Dynamic templating syntax: {{ field_logical_name_on_form }}
With nested objects such as a Lookup field, you can access its id or name using {{ lookup_field.id }}
or {{ lookup_field.name }}
Important
The fields you want to insert to the Lookup View must be available on the form, either visible or invisible
Reserved Token {{PolyLookupSearch}}
is a placeholder for the search text of the control.
![](https://user-images.githubusercontent.com/8686497/227269233-a144236f-5bd8-4d89-89a6-5b52690e97f7.png)
The Lookup View is also used to show information in the suggestion list. When there are more than one columns in the view, there will be a toggle button to show/hide more details for each suggestion item.
If you are not using system view as lookup view, the list of columns and the order to display depends on your fetchxml.
![](https://user-images.githubusercontent.com/8686497/229295565-c967f525-9dcd-4428-a697-4b23669ef59c.png)
The suggestion list only shows the first page of the results. The "Load more" button is available and the bottom of the list. Clicking the button will load the second page and add results to the list, and the button won't be available until users start searching again. There are indications at the end of the list to show if there are more results or not.
This is for the component to perform better and provide a better user experience as users need to refine the list using the search box instead of browsing through multiple pages in the suggestion list.
![](https://user-images.githubusercontent.com/8686497/229296060-b8a90930-fcbd-4ed1-908a-71f4fece5944.png)
![](https://user-images.githubusercontent.com/8686497/229296080-ac7bff7b-da05-4f62-9cb0-8052e29ce3ae.png)
Selected items are retrieved from the underlying relationship. When user selects an item from the suggestion list, the control will create a new associated record in the relationship. And when user removes an item from the selected items, the control will delete the associated record in the relationship.
Because of this, the component can't update the relationship in create form directly before the record is saved. You'll need to handle this case by yourself using output selected items feature below.
From v1.7.0, the first column in the Lookup View will be used as selected item text, this allows some flexibility to control which column should be displayed as selected text.
Optionally, you can provide a template in Selected Item Template
to customize the selected item text.
For example, with {{ new_aliasname }} ({{ new_email }})
, the selected item text will be displayed as "Contact Alias Name ([email protected])".
![](https://user-images.githubusercontent.com/8686497/222165377-60823008-8f46-40f2-bc52-4836399f1461.png)
The selected items display text, as discussed in the previous section, can be output as a comma-separated string to the Bound Field. When the selected items are changed, output will be updated accordingly.
You can leverage this feature to handle the change event of the output field to add more logic when selected items are changed.
This can be enabled optionally in the control properties.
![](https://user-images.githubusercontent.com/8686497/227786765-5abd1bb7-039b-4a4b-b332-6a33d1745cb6.png)
Additionally, the selected items can be output as a JSON array with the below schema. You'll need to specify what field you want to output the result to in the Output Selected Field
.
[{
"id": "<Selected item Guid>",
"name": "<Selected item text>",
"etn": "<Selected item entity name>"
},
{
"id": "<Selected item Guid>",
"name": "<Selected item text>",
"etn": "<Selected item entity name>"
}]
You must use this feature if you want to use the component in the create form. Then create a plugin triggered after the record is saved/created, the plugin should associate the current record with selected records stored in the JSON array.
Please see the sample plugin under Samples
folder here
Note
You don't need to handle this on update because the component can update the relationship directly when the current record already exists.
When the field is set as read-only in form designer, the control is disabled respectively.
![](https://user-images.githubusercontent.com/8686497/222163408-64884fba-0473-4b89-91e5-a5c8ddc04796.png)
![](https://user-images.githubusercontent.com/8686497/230455466-7f44613b-df84-43a1-b5f9-09a22b367009.png)
Should Output Selected Text
should be enabled for this to work
you can add your own language by passing a URL to a .resx web resource to the Language Pack Path
property.
you can use the default English language pack here PolyLookup.1033.resx as the template to create a new resx web resource in your environment, then update the value in your language.
you can use this VS Code extension to help you edit the resx web resource in a user interface https://marketplace.visualstudio.com/items?itemName=DominicVonk.vscode-resx-editor
For example, the resx web resource looks like this
![resx web resource](https://private-user-images.githubusercontent.com/8686497/355099613-40799980-dc7f-4225-bbb6-b8085d1ca973.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0OTI0NTksIm5iZiI6MTczOTQ5MjE1OSwicGF0aCI6Ii84Njg2NDk3LzM1NTA5OTYxMy00MDc5OTk4MC1kYzdmLTQyMjUtYmJiNi1iODA4NWQxY2E5NzMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTRUMDAxNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YmIzYmJkZDcwMzE0ZWYzMmIzZjMxZGQwNTYxNWUyMmIzOWE4MzA3NWM2NzA2NTE0NTFmYzM0MTc1YmYzYjYyZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.E3tDXr59HJXvYA0miubyZ-RonjWskYl7ysg_0Z4PTG8)
the value passed to the Language Pack Path
can be relative and won't need the environment part. it looks like this:
/WebResources/storm_/resx/PolyLookup.1031.resx
- ❌ Association doesn't work in create form as related records can only be linked when the current record exists after saved.
- ❌ Lookup View may not work if it's too long/complex with lots of conditions
- ❌ Bulk edit is not supported
- ❌ Can't output selected items larger than output field's maximum length
- ❌ N:N relationship is not supported in Mobile Offline Mode. More details here: https://learn.microsoft.com/en-us/power-apps/mobile/offline-capabilities#limitations
- bug fixes
- enhancements
- fixed minor bugs
- supports new look
- added tag icon
- selected items won't show up in dropdown list again to avoid duplication
- dynamic Lookup View configuration.
- clickable selected item tags when control is readonly.
- wildcard search when default search is used.
- fixed a bug where underline character (
_
) is escaped whenLIKE
operators (contains
,begins with
,ends with
) are used in filter
- added language support
- fixed dynamic templating variables not refreshing cache causing suggestion results loaded incorrectly
- fixed selected values not loaded in inactive form
- added Connection relationship type.
- fixed selected items not loaded in readonly form.
- fixed control display error in form editor.
- Upgraded handlebars fixing errors when building the component.
- Fixed a bug in custom N-N mode, selected items is not showing when associated table primary id column and intersect table lookup column have different logical names.
- Fixed a bug where suggestion list is not showing when lookup view name is blank.
- Fixed a bug where selected values are replicated when there are more than one PolyLookup components on the form.
- Supports Custom N:N relationship type
- Added ability to search using a System View for Lookup View
- Fix JSON output in the create form
- Added load more button for paging
- Added prop to output selected items as a JSON array
- Added suggestion item details using Lookup View
- Added Dynamic Search Filter
- Added Quick Create button
- Added page limit prop
- First release
- ⏹️ Permission Handling
- ✅ Error Handling
- ✅ Localization
- ⏹️ unit test & code coverage