{"id":24095,"date":"2020-07-13T10:58:57","date_gmt":"2020-07-13T10:58:57","guid":{"rendered":"https:\/\/www.inogic.com\/blog\/?p=24095"},"modified":"2021-12-06T14:58:22","modified_gmt":"2021-12-06T09:28:22","slug":"how-to-work-with-pcf-dataset-control-using-fluent-uis-detail-list","status":"publish","type":"post","link":"https:\/\/www.inogic.com\/blog\/2020\/07\/how-to-work-with-pcf-dataset-control-using-fluent-uis-detail-list\/","title":{"rendered":"How to Work with PCF Dataset Control using Fluent UI\u2019s Detail List"},"content":{"rendered":"<h2><strong>Introduction<\/strong><\/h2>\n<p>With the introduction of PowerApps Component Framework, Microsoft has provided a way to replace OOB grid and Entity fields with custom controls.<\/p>\n<p>These controls are reusable and can be designed in any form using web development technologies (HTML, CSS, Javascript) to show the CRM records like showing records in a form of Kanban Board, Sentiment analysis control, and many more.<\/p>\n<p>Apart from basic web development technologies (HTML, CSS, Javascript), we can also use various modern frameworks and libraries which expands the scope of development implementation.<\/p>\n<p>In this blog, we will see the basic of PCF (PowerApps Component Framework) dataset control i.e. replace OOB grid with our custom PCF grid and also the offerings which are provided to us in PCF <strong>context.<\/strong><\/p>\n<p>To keep dataset designing simple and easy to understand we will be using the <strong>React Fluent UI<\/strong> (previously known as React Fabric UI) framework\u2019s <a href=\"https:\/\/developer.microsoft.com\/en-us\/fabric#\/controls\/web\/detailslist\/basic.\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>\u201cDetailsList &#8211; Basic \u201c<\/strong><\/a> control in our example.<\/p>\n<p>It is not necessary that you have to use <strong>\u201cDetailsList &#8211; Basic\u201c <\/strong>control or any other react designing framework. You can also use simple HTML, JavaScript, and CSS for your dataset grid as the designing is based on developers.<\/p>\n<h2><strong>Prerequisites<\/strong><\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/powerapps\/developer\/component-framework\/get-powerapps-cli\" target=\"_blank\" rel=\"noopener noreferrer\">Microsoft PowerApps CLI<\/a> should be installed.<\/li>\n<li><a href=\"https:\/\/reactjs.org\/tutorial\/tutorial.html\" target=\"_blank\" rel=\"noopener noreferrer\">React JS<\/a> basic knowledge.<\/li>\n<li>Should be familiar with PCF control lifecycle methods e.g. <a href=\"https:\/\/docs.microsoft.com\/en-us\/powerapps\/developer\/component-framework\/reference\/control\/init\" target=\"_blank\" rel=\"noopener noreferrer\">init()<\/a>, <a href=\"https:\/\/docs.microsoft.com\/en-us\/powerapps\/developer\/component-framework\/reference\/control\/updateview\" target=\"_blank\" rel=\"noopener noreferrer\">updateView()<\/a>, and ControlManifest.Input.xml file.<\/li>\n<\/ul>\n<h2>PCF Overview<\/h2>\n<p><strong>Step 1<\/strong>:\u00a0 Creating a PCF project.<\/p>\n<p>Follow the following <a href=\"https:\/\/docs.microsoft.com\/en-us\/powerapps\/developer\/component-framework\/create-custom-controls-using-pcf\" target=\"_blank\" rel=\"noopener noreferrer\">link<\/a> for creating the boilerplate React project.<\/p>\n<p>Before coding let us see some of the important aspects of PCF control.<\/p>\n<p>When you create a PCF project you will see there are four methods i.e. init, updateView, getOutputs, destroy which are already present in the index.ts file and a couple of them have parameters as shown in the below screenshot.<\/p>\n<p>We will walk through some of them which we will be using in our details list.<\/p>\n<p><a href=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/1PCF-Dataset-Control.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"aligncenter wp-image-24102\" style=\"border: 1px solid #0a0a0a; padding: 1px; margin: 1px;\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/1PCF-Dataset-Control.png\" alt=\"PCF Dataset Control\" width=\"969\" height=\"167\" srcset=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/1PCF-Dataset-Control.png 940w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/1PCF-Dataset-Control-300x52.png 300w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/1PCF-Dataset-Control-768x132.png 768w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/1PCF-Dataset-Control-660x114.png 660w\" sizes=\"(max-width: 969px) 100vw, 969px\" \/><\/a><\/p>\n<p><strong>Context:<\/strong> In the init and the updateView view you will get the function parameter as a context object.<\/p>\n<p>It provides all the properties and methods available in the PowerApps Component Framework i.e. Webapi methods, Utility, Navigation, Device Info, Client Info, etc.<\/p>\n<p><strong>Container: <\/strong>\u00a0Container variable is used to append our custom grid over OOB grid.<\/p>\n<p>Now the question arises on how to get and use CRM data in our control?<\/p>\n<p><strong>How to get CRM data?<\/strong><\/p>\n<p>By default, in a context variable we get all the columns and record info that is available\/can be seen in the OOB grid as a parameter. To access\/use it we need to use attributes that are provided in the context variable. Given below are the few commonly used attributes in PCF dataset control.<\/p>\n<p><strong>Columns information:<\/strong><\/p>\n<p><strong>Context.parameters.sampledataset\u00a0 &#8211;<\/strong> This attribute will give you all the OOB grid information like columns, page records, paging info, etc.<\/p>\n<p>Below is a screenshot of the context properties which you can check while debugging.<\/p>\n<p><a href=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-24103\" style=\"border: 1px solid #0a0a0a; padding: 1px; margin: 1px;\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control.png\" alt=\"PCF Dataset Control\" width=\"1440\" height=\"393\" srcset=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control.png 1440w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control-300x82.png 300w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control-768x210.png 768w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control-1024x279.png 1024w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/2PCF-Dataset-Control-660x180.png 660w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/a><\/p>\n<p><strong>Context.parameters.sampledataset.columns<\/strong> \u2013 It will give us an array of objects which contain all the column information including Logical name, Display name datatype of the column.<\/p>\n<p><a href=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/3PCF-Dataset-Control-1.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"aligncenter wp-image-24104\" style=\"border: 1px solid #0a0a0a; padding: 1px; margin: 1px;\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/3PCF-Dataset-Control-1.png\" alt=\"PCF Dataset Control\" width=\"947\" height=\"159\" srcset=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/3PCF-Dataset-Control-1.png 916w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/3PCF-Dataset-Control-1-300x50.png 300w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/3PCF-Dataset-Control-1-768x129.png 768w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/3PCF-Dataset-Control-1-660x111.png 660w\" sizes=\"(max-width: 947px) 100vw, 947px\" \/><\/a><\/p>\n<p><strong>Context.parameter.sampleDatset.records &#8211; <\/strong>As you can see in the below screenshot, it will give all the page records value which was in OOB column views.<\/p>\n<p>If the default paging size is 50 then you will get 50 records that are present on the page. Similarly, if the paging size is 100 you will get 100 records using <strong>context.parameter.sampleDatset.records-<\/strong><\/p>\n<p><a href=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-24105\" style=\"border: 1px solid #0a0a0a; padding: 1px; margin: 1px;\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1.png\" alt=\"PCF Dataset Control\" width=\"1422\" height=\"690\" srcset=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1.png 1422w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1-300x146.png 300w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1-768x373.png 768w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1-1024x497.png 1024w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/4PCF-Dataset-Control-1-660x320.png 660w\" sizes=\"(max-width: 1422px) 100vw, 1422px\" \/><\/a><\/p>\n<h2>Code Implementation<\/h2>\n<p>For using <strong>\u201cDetailsList &#8211; Basic\u201c control<\/strong> we have to just pass parameters (props) in a certain format which will then load our custom grid.<\/p>\n<p>Here is the code for loading custom grid (DetailsList \u2013 Basic) \u2013<\/p>\n<p><strong>Index.ts<\/strong><\/p>\n<p>1. Add the below import in your index.ts file. You don\u2019t need to install react and react-dom since it would be already installed when you create a project.<\/p>\n<p>import\u00a0*\u00a0as\u00a0React\u00a0from\u00a0&#8216;react&#8217;;<\/p>\n<p>import\u00a0*\u00a0as\u00a0ReactDOM\u00a0from\u00a0&#8216;react-dom&#8217;;<\/p>\n<p>\/\/React component which we will create<\/p>\n<p>import\u00a0{\u00a0DetailsListGrid\u00a0}\u00a0from\u00a0&#8220;.\/components\/DetailsListGrid&#8221;;<\/p>\n<p>2. Declare a global variable which will store the default CRM grid object<\/p>\n<p>private\u00a0_container:\u00a0any<\/p>\n<p>3. In the init function, we will initialize the global variable with the default CRM grid object.<\/p>\n<p>public\u00a0init(context:\u00a0ComponentFramework.Context&lt;IInputs&gt;,\u00a0notifyOutputChanged:\u00a0()\u00a0=&gt;\u00a0void,\u00a0state:\u00a0ComponentFramework.Dictionary,\u00a0container:\u00a0HTMLDivElement)\u00a0{<\/p>\n<p>this._container\u00a0=\u00a0container<\/p>\n<p>}<\/p>\n<p>4. In updateView, we will write all the logic to append our custom grid over default CRM\u2019s OOB grid.<\/p>\n<p>public\u00a0updateView(context:\u00a0ComponentFramework.Context&lt;IInputs&gt;):\u00a0void\u00a0{<\/p>\n<p>let\u00a0functionName:\u00a0string\u00a0=\u00a0&#8220;updateView&#8221;;<\/p>\n<p>\/\/\u00a0all\u00a0columns\u00a0which\u00a0are\u00a0on\u00a0views(Eg\u00a0Active\u00a0account)<\/p>\n<p>let\u00a0columnsOnView\u00a0=\u00a0context.parameters.sampleDataSet.columns;<\/p>\n<p>let\u00a0mappedcolumns\u00a0=\u00a0this.mapCRMColumnsToDetailsListColmns(columnsOnView);<\/p>\n<p>let\u00a0pageRows\u00a0=\u00a0this.getAllPageRecords(columnsOnView,\u00a0context.parameters.sampleDataSet)<\/p>\n<p>try\u00a0{<\/p>\n<p>this.renderDatasetGrid(context,\u00a0mappedcolumns,\u00a0pageRows)<\/p>\n<p>}\u00a0catch\u00a0(error)\u00a0{<\/p>\n<p>console.log(functionName\u00a0+\u00a0&#8221;\u00a0+\u00a0error);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>\/**<\/p>\n<p>* Render DetailsListGrid<\/p>\n<p>*\/<\/p>\n<p>public renderDatasetGrid(context: ComponentFramework.Context&lt;IInputs&gt;, mappedcolumns: any, pageRows: any) {<\/p>\n<p>let functionName = &#8216;renderDatasetGrid&#8217;;<\/p>\n<p>let appProps: any<\/p>\n<p>try {<\/p>\n<p>\/\/ props to be passed to component.<\/p>\n<p>appProps = {<\/p>\n<p>mappedcolumns: mappedcolumns, \/\/ formatted columns for\u00a0 details list<\/p>\n<p>pageRows: pageRows, \/\/ page records value<\/p>\n<p>pcfContext: context \/\/ pcf context<\/p>\n<p>};<\/p>\n<p>ReactDOM.render(React.createElement(DetailsListGrid, appProps), this._container);<\/p>\n<p>} catch (error) {<\/p>\n<p>console.log(functionName + &#8221; + error);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>\/**<\/p>\n<p>*\u00a0Get\u00a0all\u00a0page\u00a0record\u00a0column\u00a0value.<\/p>\n<p>*\u00a0@param\u00a0columnsOnView<\/p>\n<p>*\u00a0@param\u00a0gridParam<\/p>\n<p>*\/<\/p>\n<p>public\u00a0getAllPageRecords(columnsOnView:\u00a0DataSetInterfaces.Column[],<\/p>\n<p>gridParam:\u00a0DataSet)\u00a0{<\/p>\n<p>let\u00a0functionName\u00a0=\u00a0&#8216;loadPagingRecords&#8217;;<\/p>\n<p>let\u00a0pagingDataRows:\u00a0any\u00a0=\u00a0[];<\/p>\n<p>let\u00a0currentPageRecordsID\u00a0=\u00a0gridParam.sortedRecordIds;<\/p>\n<p>try\u00a0{<\/p>\n<p>for\u00a0(const\u00a0pointer\u00a0in\u00a0currentPageRecordsID)\u00a0{<\/p>\n<p>pagingDataRows[pointer]\u00a0=\u00a0{}<\/p>\n<p>pagingDataRows[pointer][&#8220;key&#8221;]\u00a0=\u00a0currentPageRecordsID[pointer];<\/p>\n<p>columnsOnView.forEach((columnItem:\u00a0any,\u00a0index)\u00a0=&gt;\u00a0{<\/p>\n<p>pagingDataRows[pointer][columnItem.name]\u00a0=\u00a0gridParam.records[currentPageRecordsID[pointer]].getFormattedValue(columnItem.name);<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}\u00a0catch\u00a0(error)\u00a0{<\/p>\n<p>console.log(functionName\u00a0+\u00a0&#8221;\u00a0+\u00a0error);<\/p>\n<p>}<\/p>\n<p>return\u00a0pagingDataRows;<\/p>\n<p>}<\/p>\n<p>\/**<\/p>\n<p>*\u00a0Convert\u00a0our\u00a0columns\u00a0in\u00a0a format\u00a0which\u00a0is\u00a0accepted\u00a0by\u00a0DetailsList\u00a0grid<\/p>\n<p>*\u00a0@param\u00a0columnsOnView\u00a0columns\u00a0available\u00a0on\u00a0views<\/p>\n<p>*\/<\/p>\n<p>public\u00a0mapCRMColumnsToDetailsListColmns(columnsOnView:\u00a0any):\u00a0any\u00a0{<\/p>\n<p>let\u00a0functionName\u00a0=\u00a0&#8216;mapCRMColumnsToDetailsListColmns&#8217;;<\/p>\n<p>let\u00a0mappedColumn\u00a0=\u00a0[]\n<p>try\u00a0{<\/p>\n<p>\/\/\u00a0loop\u00a0thorugh\u00a0all\u00a0columns<\/p>\n<p>for\u00a0(const\u00a0pointer\u00a0in\u00a0columnsOnView)\u00a0{<\/p>\n<p>mappedColumn.push({<\/p>\n<p>key:\u00a0pointer,<\/p>\n<p>name:\u00a0columnsOnView[pointer].displayName,<\/p>\n<p>fieildName:\u00a0columnsOnView[pointer].name,<\/p>\n<p>minWidth:\u00a0150,<\/p>\n<p>maxWidth:\u00a0200,<\/p>\n<p>isResizable:\u00a0true,<\/p>\n<p>onColumnClick:\u00a0()\u00a0=&gt;\u00a0{<\/p>\n<p>alert(`Column\u00a0${columnsOnView[pointer].displayName}\u00a0clicked`);<\/p>\n<p>},<\/p>\n<p>data:\u00a0&#8220;string&#8221;,<\/p>\n<p>onRender:\u00a0(item:\u00a0any)\u00a0=&gt;\u00a0{<\/p>\n<p>return\u00a0React.createElement(&#8216;span&#8217;,\u00a0null,\u00a0item[columnsOnView[pointer].name])<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>})<\/p>\n<p>}<\/p>\n<p>}\u00a0catch\u00a0(error)\u00a0{<\/p>\n<p>console.log(functionName\u00a0+\u00a0&#8221;\u00a0+\u00a0error);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>return\u00a0mappedColumn;<\/p>\n<p>}<\/p>\n<p>5. We will remove the control from DOM when it is not required which will be handled by the destroy function that is invoked automatically.<\/p>\n<p>public\u00a0destroy():\u00a0void\u00a0{<\/p>\n<p>ReactDOM.unmountComponentAtNode(this._container);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<h2><strong>DetailsListGrid.tsx (Create this React component with name)<\/strong><\/h2>\n<p>Create a file with extension .tsx in your project e.g. DetailsListGrid.tsx and copy the below code:<\/p>\n<p>1. Install React fluent UI library using integrated terminal &#8211; <strong>npm i\u00a0office-ui-fabric-react @fluentui\/react<\/strong><\/p>\n<p>import\u00a0*\u00a0as\u00a0React\u00a0from\u00a0&#8220;react&#8221;;<\/p>\n<p>import\u00a0{<\/p>\n<p>DetailsList,<\/p>\n<p>DetailsListLayoutMode,<\/p>\n<p>Selection<\/p>\n<p>}\u00a0from\u00a0&#8220;office-ui-fabric-react\/lib\/DetailsList&#8221;;<\/p>\n<p>import\u00a0{\u00a0MarqueeSelection\u00a0}\u00a0from\u00a0&#8220;office-ui-fabric-react\/lib\/MarqueeSelection&#8221;;<\/p>\n<p>import\u00a0{\u00a0Fabric\u00a0}\u00a0from\u00a0&#8220;office-ui-fabric-react\/lib\/Fabric&#8221;;<\/p>\n<p>export\u00a0interface\u00a0IDetailsListBasicExampleItem\u00a0{<\/p>\n<p>key:\u00a0number;<\/p>\n<p>name:\u00a0string;<\/p>\n<p>value:\u00a0number;<\/p>\n<p>}<\/p>\n<p>export\u00a0interface\u00a0IDetailsListBasicExampleState\u00a0{<\/p>\n<p>items:\u00a0any;<\/p>\n<p>}<\/p>\n<p>export\u00a0class\u00a0DetailsListGrid\u00a0extends\u00a0React.Component&lt;<\/p>\n<p>any,<\/p>\n<p>IDetailsListBasicExampleState<\/p>\n<p>&gt;\u00a0{<\/p>\n<p>private\u00a0_selection:\u00a0Selection;<\/p>\n<p>private\u00a0_allItems:\u00a0any\u00a0=\u00a0this.props.pageRows;<\/p>\n<p>private\u00a0_columns:\u00a0any\u00a0=\u00a0this.props.mappedcolumns;<\/p>\n<p>private\u00a0_pcfContext\u00a0=\u00a0this.props.pcfContext;<\/p>\n<p>private\u00a0_allSelectedCards:\u00a0any\u00a0=\u00a0[];<\/p>\n<p>constructor(props:\u00a0{})\u00a0{<\/p>\n<p>super(props);<\/p>\n<p>this._selection\u00a0=\u00a0new\u00a0Selection({<\/p>\n<p>onSelectionChanged:\u00a0()\u00a0=&gt;\u00a0{<\/p>\n<p>\/\/\u00a0@ts-ignore<\/p>\n<p>this.onRowSelection(this._selection._anchoredIndex);<\/p>\n<p>}<\/p>\n<p>});<\/p>\n<p>\/\/\u00a0Populate\u00a0with\u00a0items\u00a0for\u00a0demos.<\/p>\n<p>this.state\u00a0=\u00a0{<\/p>\n<p>items:\u00a0this._allItems<\/p>\n<p>};<\/p>\n<p>}<\/p>\n<p>public\u00a0render():\u00a0JSX.Element\u00a0{<\/p>\n<p>const\u00a0{\u00a0items\u00a0}\u00a0=\u00a0this.state;<\/p>\n<p>return\u00a0(<\/p>\n<p>&lt;Fabric&gt;<\/p>\n<p>&lt;MarqueeSelection\u00a0selection={this._selection}&gt;<\/p>\n<p>&lt;DetailsList<\/p>\n<p>items={items}<\/p>\n<p>columns={this._columns}<\/p>\n<p>setKey=&#8221;set&#8221;<\/p>\n<p>layoutMode={DetailsListLayoutMode.justified}<\/p>\n<p>selection={this._selection}<\/p>\n<p>selectionPreservedOnEmptyClick={true}<\/p>\n<p>ariaLabelForSelectionColumn=&#8221;Toggle\u00a0selection&#8221;<\/p>\n<p>ariaLabelForSelectAllCheckbox=&#8221;Toggle\u00a0selection\u00a0for\u00a0all\u00a0items&#8221;<\/p>\n<p>checkButtonAriaLabel=&#8221;Row\u00a0checkbox&#8221;<\/p>\n<p>onItemInvoked={this._onItemInvoked}<\/p>\n<p>\/&gt;<\/p>\n<p>&lt;\/MarqueeSelection&gt;<\/p>\n<p>&lt;\/Fabric&gt;<\/p>\n<p>);<\/p>\n<p>}<\/p>\n<p>\/**<\/p>\n<p>*\u00a0Function\u00a0to\u00a0change\u00a0the ribbon\u00a0bar\u00a0of\u00a0CRM.<\/p>\n<p>*\/<\/p>\n<p>private\u00a0onRowSelection\u00a0=\u00a0(rowIndex:\u00a0number)\u00a0=&gt;\u00a0{<\/p>\n<p>let\u00a0functionName:\u00a0string\u00a0=\u00a0&#8220;onRowSelection&#8221;;<\/p>\n<p>let\u00a0selectedRowId:\u00a0string;<\/p>\n<p>let\u00a0selectedCardIndex:\u00a0number;<\/p>\n<p>try\u00a0{<\/p>\n<p>selectedRowId\u00a0=\u00a0this.props.pageRows[rowIndex].key;<\/p>\n<p>\/\/\u00a0check\u00a0if\u00a0selected\u00a0row\u00a0is\u00a0alrady\u00a0seelected<\/p>\n<p>selectedCardIndex\u00a0=\u00a0this._allSelectedCards.findIndex((element:\u00a0any)\u00a0=&gt;\u00a0{<\/p>\n<p>return\u00a0element\u00a0==\u00a0selectedRowId;<\/p>\n<p>});<\/p>\n<p>\/\/\u00a0if\u00a0card\u00a0is\u00a0already\u00a0clicked\u00a0remove\u00a0card\u00a0id<\/p>\n<p>if\u00a0(selectedCardIndex\u00a0&gt;=\u00a00)\u00a0{<\/p>\n<p>this._allSelectedCards.splice(selectedCardIndex,\u00a01);<\/p>\n<p>}\u00a0else\u00a0{<\/p>\n<p>\/\/\u00a0store\u00a0all\u00a0selected\u00a0card\u00a0in\u00a0array<\/p>\n<p>this._allSelectedCards.push(selectedRowId);<\/p>\n<p>}<\/p>\n<p>\/\/\u00a0update\u00a0ribbon\u00a0bar<\/p>\n<p>this._pcfContext.parameters.sampleDataSet.setSelectedRecordIds(<\/p>\n<p>this._allSelectedCards<\/p>\n<p>);<\/p>\n<p>}\u00a0catch\u00a0(error)\u00a0{<\/p>\n<p>console.log(functionName\u00a0+\u00a0&#8220;&#8221;\u00a0+\u00a0error);<\/p>\n<p>}<\/p>\n<p>};<\/p>\n<p>\/**<\/p>\n<p>*\u00a0Call\u00a0function\u00a0to\u00a0open\u00a0Entity\u00a0record<\/p>\n<p>*\/<\/p>\n<p>private\u00a0_onItemInvoked\u00a0=\u00a0(item:\u00a0IDetailsListBasicExampleItem):\u00a0void\u00a0=&gt;\u00a0{<\/p>\n<p>\/\/\u00a0function\u00a0to\u00a0open\u00a0entity\u00a0record<\/p>\n<p>this.openEntityRecord(item.key);<\/p>\n<p>};<\/p>\n<p>\/**<\/p>\n<p>*\u00a0Open\u00a0selected\u00a0entity\u00a0record<\/p>\n<p>*\u00a0@param\u00a0event<\/p>\n<p>*\/<\/p>\n<p>private\u00a0openEntityRecord(recordID:\u00a0any):\u00a0void\u00a0{<\/p>\n<p>let\u00a0functionName:\u00a0string\u00a0=\u00a0&#8220;onCardDoubleClick&#8221;;<\/p>\n<p>try\u00a0{<\/p>\n<p>if\u00a0(recordID\u00a0!=\u00a0null\u00a0||\u00a0recordID\u00a0!=\u00a0undefined)\u00a0{<\/p>\n<p>let\u00a0entityreference\u00a0=\u00a0this._pcfContext.parameters.sampleDataSet.records[<\/p>\n<p>recordID<\/p>\n<p>].getNamedReference();<\/p>\n<p>let\u00a0entityFormOptions\u00a0=\u00a0{<\/p>\n<p>entityName:\u00a0entityreference.LogicalName,<\/p>\n<p>entityId:\u00a0entityreference.id<\/p>\n<p>};<\/p>\n<p>\/**\u00a0Using\u00a0navigation\u00a0method\u00a0*\/<\/p>\n<p>this._pcfContext.navigation<\/p>\n<p>.openForm(entityFormOptions)<\/p>\n<p>.then((success:\u00a0any)\u00a0=&gt;\u00a0{<\/p>\n<p>console.log(success);<\/p>\n<p>})<\/p>\n<p>.catch((error:\u00a0any)\u00a0=&gt;\u00a0{<\/p>\n<p>console.log(error);<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}\u00a0catch\u00a0(error)\u00a0{<\/p>\n<p>console.log(functionName\u00a0+\u00a0&#8220;&#8221;\u00a0+\u00a0error);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>Final Component<\/p>\n<p>After deploying your control and configuring it on the entity you will see the OOB Grid has been replaced with our own <strong>React Fluent UI Detail List Grid.<\/strong><\/p>\n<p><a href=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-24106\" style=\"border: 1px solid #0a0a0a; padding: 1px; margin: 1px;\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1.png\" alt=\"PCF Dataset Control\" width=\"1233\" height=\"679\" srcset=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1.png 1233w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1-300x165.png 300w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1-768x423.png 768w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1-1024x564.png 1024w, https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2020\/07\/5PCF-Dataset-Control-1-660x363.png 660w\" sizes=\"(max-width: 1233px) 100vw, 1233px\" \/><\/a><\/p>\n<h2><strong>Conclusion<\/strong><\/h2>\n<p>As illustrated above, you can now easily work with PCF Dataset Control using Fluent UI\u2019s Detail List.<\/p>\n<h2 style=\"text-align: left;\"><div class=\"su-heading su-heading-style-default su-heading-align-center\" id=\"\" style=\"font-size:15px;margin-bottom:5px\"><div class=\"su-heading-inner\">One Pic = 1000 words! Analyze data 90% faster with visualization apps!<\/div><\/div><\/h2>\n<p style=\"text-align: left;\"><em>Get optimum visualization of Dynamics 365 CRM data with &#8211;<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3lYvozZ\" target=\"_blank\" rel=\"noopener noreferrer\">Kanban Board<\/a> <\/strong>\u2013 Visualize Dynamics 365 CRM data in Kanban view by categorizing entity records in lanes and rows as per their status, priority, etc.<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3lCSBaA\" target=\"_blank\" rel=\"noopener noreferrer\">Map My Relationships<\/a><\/strong> \u2013 Map My Relationships \u2013 Visualize connections and relationships between Dynamics 365 CRM entities or related records in a Mind Map view.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction With the introduction of PowerApps Component Framework, Microsoft has provided a way to replace OOB grid and Entity fields with custom controls. These controls are reusable and can be designed in any form using web development technologies (HTML, CSS, Javascript) to show the CRM records like showing records in a form of Kanban Board,\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.inogic.com\/blog\/2020\/07\/how-to-work-with-pcf-dataset-control-using-fluent-uis-detail-list\/\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":13,"featured_media":24101,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[16,18,1929],"tags":[],"class_list":["post-24095","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dynamics-365","category-dynamics-365-v9-2","category-pcf"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts\/24095","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/comments?post=24095"}],"version-history":[{"count":0,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts\/24095\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/media\/24101"}],"wp:attachment":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/media?parent=24095"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/categories?post=24095"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/tags?post=24095"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}