Dataverse PCF control for N:N relationship and muti-lookup
As we know: the Lookup field is one of the standard types that Microsoft provide for Dynamics 365 and use to bring other entity on a form. However, it is not enough for Users. I have faced this issue in real projects based on business logic from customers. Today I will show you an approach to achieve this goal by using PCF control and Plugins via an example: Create multiple lookups on Opportunity form and this field is used to link multiple Accounts to Opportunity base on the NN relationship.
The main idea is: we will use a single line of text to store the GUID of lookup values. The PCF will render this field as a multiple lookup and we will create real relationships in the backend (plugins).
We'll complete the following steps:
1. What is PCF?
PCF Tutorial Dynamics 365: PCF (PowerApps component framework) empowers professional developers and app makers to create code components for model-driven apps and canvas apps (experimental preview) to provide an enhanced user experience for the users to view and work with data in forms, views, and dashboards. For example:
- Replace a field that displays a numeric text value with a dial or slider code component.
- Transform a list into an entirely different visual experience bound to the data set like a Calendar or Map.
If you do not have knowledge about how to set up, build and deploy PCF project, please have look at the article here.
2. PCF Multiple Lookup
1. What does the PCF Multiple Lookup do?
- Render to Multiple Lookup from a single line of text: thanks to select2 library.
- Search linked records base on the user's input
- Display existing linked records base on the existing relationships between them
When load the control, the control will retrieve list of existing relationships before rendering the lookup fieldcontext.webAPI.retrieveMultipleRecords(this._linkedEntitySchemaName, `?$select=${this._linkedEntityIdSchemaName},${this._linkedEntityPrimaryField}${additionalSelect}${filterString}`).then((result) => { this._select2Data = result.entities; this._select2Data.forEach((item) => { item.id = item[this._linkedEntityIdSchemaName]; item.text = item[this._linkedEntityPrimaryField]; item.selected = true; }); this.initializeSelect2(); }, (error) => { console.log(error); });
Then, the User Interface will be like that:
- Display existing linked records base on existing GUID
- Store a string that is merged from GUID of lookup values (GUID of Accounts in my example) and PCF as ending. For example: "guid1,guid2,PCF". You could be ambiguous with the question "Why does it contain PCF at the end?". Well, it is just a signal to recognize event onChange in case user at data then remove everything.
2. How to use?
- Install solution: we have 2 ways:
- Clone the source code and Deploy directly from VS Code: You can deploy the code components directly from Microsoft Power Platform CLI by connecting to the Dataverse environment and then pushing the updated components.
Follow the steps below to create the authentication profile, connect to Dataverse, and push the updated components.- Create your authentication profile using the command:
pac auth create --url https://xyz.crm.dynamics.com
-
If you have previously created an authentication profile, you can view all the existing profiles using the command:
pac auth list
-
To switch between the previously created authentication profiles, use the command:
pac auth select --index <index of the active profile>
-
To get the basic information about the environment, use the following command. The connection will be made using the default authentication profile.
pac org who
-
To delete a particular authentication profile, use the command
pac auth delete --index <index of the profile>
. -
If you want to clear all the authentication profiles from your local machine, use the command
pac auth clear
. This action is irreversible because it completely deletes theauthprofile.json
file and token cache file from your local machine. -
After you have successfully created an authentication profile, you can start pushing the code components to the Dataverse instance with all the latest changes with command
pac pcf push --publisher-prefix <your publisher prefix>
You could find the document from Microft for more details.
- Create your authentication profile using the command:
- Download and Import managed solution from here:
- Clone the source code and Deploy directly from VS Code: You can deploy the code components directly from Microsoft Power Platform CLI by connecting to the Dataverse environment and then pushing the updated components.
- Create a single line of text field to render the mutiple lookup: In my case, I create a field name TechnicalMultipleLookup
- Add this field to form and open field properties
- Select control MultipleLookupImplementationv8 which is imported from solution above.
- Then configure parameters for the Control:
Parameter |
Description |
Main Field | Main Field bound to control |
Relationship Entity Type |
Relationship Entity Type (Default or custom) - Custom: Activity entity (Phonecall, Email, Task, ...) don't support NN relationship. We need to create entity to simulate this relationship. For example, we need create entity AccountTask which contains lookup to Account and Task to simulate NN Relationship between Account and Task. - Default: the OOTB NN relationship. We should prefer this type. Only use customer for case of Activity |
Linked Entity Schema Name | Name of relate entity |
Linked Entity Plural Name | Plural Name of relate entity |
Linked Entity Primary Field | Linked Entity Primary Field |
Linked Entity ID Attribute | Linked Entity ID Attribute |
Relationship Entity | Relationship Entity |
Relationship Entity plural name | Relationship Entity plural name |
Relationship Main Entity Field | Lookup field to primary entity in relationship |
Relationship Relate Entity Field | Lookup field to related entity in relationship |
Main Entity plural name | Main Entity plural name |
Filter Attribute | Filtering condition for lookup search |
a
Here my example:
Then now we could search as lookup field:
For each Account in this multiple lookup, it also has hyperlink direct to account when we click on it.
What is actually the single line of text field stored?
The field store a string that is merged from GUID of lookup values (GUID of Accounts in my example) and PCF as ending. That is the reason why we need create a single line of text field to bind into multiple lookup field.
3. Create Relationship
However, it is not enough to simulate "real" multiple lookup field since the PCF only display the lookup value base on stored GUID. We are missing creating the relationship for lookup values. We have 2 approaches for creating relationships:
- Create directly in PCF by using WebApi: This approach only requires knowledge of Client-Side script (Reactjs + JavaScript) so we could have quick implementation because they have the same base. However, as my experience this approach sometimes could not give the exaction due to asynchronous request to the server, it leads to the user's experience not good. For example: if use select then remove value quickly then select again immediately, the request to server can not follow up the user's speed.
- Create the relationship in the plugin: This is best method to associate and disassociate relationships because it run at the server side. We need to handle relationship in both Create and Update event. Here is a snip code to create/remove N:N relationship between Accounts and Opportunities in plugin:n
// Associate the accounts to the opportunity record. // Create a collection of the entity ids that will be associated to the contact. var relatedEntities = new EntityReferenceCollection(); relatedEntities.Add(new EntityReference("account", _account1Id)); relatedEntities.Add(new EntityReference("account", _account2Id)); relatedEntities.Add(new EntityReference("account", _account3Id)); // Create an object that defines the relationship between the contact and account. var relationship = new Relationship("knh_opportunity_account"); //Associate the opportunity with the 3 accounts. svc.Associate("opportunity", _opportunityId, relationship, relatedEntities); //Disassociate the records. svc.Disassociate("opportunity", _contactId, relationship, relatedEntities)
4. Conslution
Added value compare to other existing PCF controls :
- Can handle “custom” NN relationship between an Activity and other entity such as: NN relationship between Account and PhoneCall.
- For this “custom” NN Relationship, we need create an “middle” entity which include 2 lookups field to Account and PhoneCall and there is no available PCF control for this.
- Beside that, my PCF control give more option to select field to display as well as config the filter query for Account.
Known issue: when you deploy the PCF again after you made some changes, the code will not be applied. In this case, you should delete existing PCF Control before deploying or changing the name of PCF Control to an unique name.
Dataverse PCF control for N:N relationship and muti-lookup
Comments
Associate the Opportunity with the selected accounts
Hi
is it possible to view the opportunity on the selected account, I mean associate the opportunity with the multi accounts selected on the opportunity.
Many Thanks