Updated documentation

This commit is contained in:
Hugo Bernier 2021-01-07 02:48:21 -05:00
parent fb90f24c00
commit 8bbce1a50f
3 changed files with 64 additions and 24 deletions

View File

@ -414,4 +414,61 @@ ReactContentQuery.ExternalScripts.MyCustomBlockHelper = {
} }
``` ```
### Using Microsoft Graph Toolkit
The Content Query Web Part provides support for [Microsoft Graph Toolkit](https://docs.microsoft.com/en-us/graph/toolkit/overview) (MGT) integration to easily query the [Microsoft Graph](https://docs.microsoft.com/en-us/graph/overview) within your handlebars templates.
You can use any of the MGT components without additional steps, although the MGT integration was designed specifically with [Person](https://docs.microsoft.com/en-us/graph/toolkit/components/person), [People](https://docs.microsoft.com/en-us/graph/toolkit/components/people), and [Person card](https://docs.microsoft.com/en-us/graph/toolkit/components/person-card) components.
#### Using MGT with a person field
If you have a SharePoint list containing a user field (like a **Created By** or **Modified By** field) or a person field, you can pass the `email` property from field's the `personValue` to the MGT component's `person-query` attribute.
For example, to use the `mgt-person` component with a person field called `MyPersonField`, you would use the following template:
```handlebars
<mgt-person person-query="{{MyPersonField.personValue.email}}" view="twoLines"></mgt-person>
```
#### Using MGT templates
MGT supports the use of custom templates to modify the content of a components.
According to [MGT documentation](https://docs.microsoft.com/en-us/graph/toolkit/customize-components/templates), the binding syntax to inject dynamic content in a template uses a block delimited by `{{` and `}}` -- which conflicts with the Handlebars binding syntax.
In order to use a custom MGT template in your Handlebars template, use `[[` and `]]` instead of `{{` and `}}` to bind to the MGT context.
For example, you would replace the following Handlebars template:
```handlebars
<mgt-person person-query="{{MyPersonField.personValue.email}}">
<template>
<div data-if="person.image">
<img src="{{ person.image }}" />
</div>
<div data-else>
{{ person.displayName }}
</div>
</template>
</mgt-person>
```
With the following template:
```handlebars
<mgt-person person-query="{{MyPersonField.personValue.email}}">
<template>
<div data-if="person.image">
<img src="[[ person.image ]]" />
</div>
<div data-else>
[[ person.displayName ]]
</div>
</template>
</mgt-person>
```
Note that, in the example above, the `person-query` attribute is still bound using the Handlebars syntax `person-query="{{MyPersonField.personValue.email}}"`, whereas the MGT template uses `[[ person.image ]]` and `[[ person.displayName ]]`.
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-web parts/samples/react-content-query-online" /> <img src="https://telemetry.sharepointpnp.com/sp-dev-fx-web parts/samples/react-content-query-online" />

View File

@ -90,16 +90,11 @@ export class ContentQueryService implements IContentQueryService {
// Builds the CAML query based on the web part settings // Builds the CAML query based on the web part settings
const query: string = CamlQueryHelper.generateCamlQuery(querySettings); const query: string = CamlQueryHelper.generateCamlQuery(querySettings);
//TODO: Remove
console.log("Query", query);
//Log.info(this.logSource, Text.format("Generated CAML query {0}...", query), this.context.serviceScope); //Log.info(this.logSource, Text.format("Generated CAML query {0}...", query), this.context.serviceScope);
// Queries the list with the generated CAML query // Queries the list with the generated CAML query
this.listService.getListItemsByQuery(querySettings.webUrl, querySettings.listId, query) this.listService.getListItemsByQuery(querySettings.webUrl, querySettings.listId, query)
.then((data: any) => { .then((data: any) => {
//TODO: Remove
console.log("List Service data", data);
// Updates the template context with the normalized query results // Updates the template context with the normalized query results
let normalizedResults = this.normalizeQueryResults(data.value, querySettings.viewFields); let normalizedResults = this.normalizeQueryResults(data.value, querySettings.viewFields);
templateContext.items = normalizedResults; templateContext.items = normalizedResults;
@ -298,8 +293,6 @@ export class ContentQueryService implements IContentQueryService {
// Otherwise gets the options asynchronously // Otherwise gets the options asynchronously
return new Promise<IDropdownOption[]>((resolve, reject) => { return new Promise<IDropdownOption[]>((resolve, reject) => {
this.listService.getListFields(webUrl, listId, ['InternalName', 'Title', 'Sortable'], 'Title').then((data: any) => { this.listService.getListFields(webUrl, listId, ['InternalName', 'Title', 'Sortable'], 'Title').then((data: any) => {
//TODO: Remove
console.log("Fields", data);
const sortableFields: any[] = data.value.filter((field) => { return field.Sortable == true; }); const sortableFields: any[] = data.value.filter((field) => { return field.Sortable == true; });
let options: IDropdownOption[] = [{ key: "", text: strings.queryFilterPanelStrings.queryFilterStrings.fieldSelectLabel }]; let options: IDropdownOption[] = [{ key: "", text: strings.queryFilterPanelStrings.queryFilterStrings.fieldSelectLabel }];
const orderByOptions: IDropdownOption[] = sortableFields.map((field) => { return { key: field.InternalName, text: Text.format("{0} \{\{{1}\}\}", field.Title, field.InternalName) }; }); const orderByOptions: IDropdownOption[] = sortableFields.map((field) => { return { key: field.InternalName, text: Text.format("{0} \{\{{1}\}\}", field.Title, field.InternalName) }; });
@ -589,10 +582,6 @@ export class ContentQueryService implements IContentQueryService {
private normalizeQueryResults(results: any[], viewFields: string[]): INormalizedResult[] { private normalizeQueryResults(results: any[], viewFields: string[]): INormalizedResult[] {
//Log.verbose(this.logSource, "Normalizing results for the requested handlebars context...", this.context.serviceScope); //Log.verbose(this.logSource, "Normalizing results for the requested handlebars context...", this.context.serviceScope);
// TODO: Remove
console.log("Results", results);
const normalizedResults: INormalizedResult[] = results.map((result) => { const normalizedResults: INormalizedResult[] = results.map((result) => {
let normalizedResult: any = {}; let normalizedResult: any = {};
let formattedCharsRegex = /_x00(20|3a|[c-f]{1}[0-9a-f]{1})_/gi; let formattedCharsRegex = /_x00(20|3a|[c-f]{1}[0-9a-f]{1})_/gi;
@ -619,9 +608,6 @@ export class ContentQueryService implements IContentQueryService {
return normalizedResult; return normalizedResult;
}); });
//TODO: Remove
console.log("Normalized results", normalizedResults);
return normalizedResults; return normalizedResults;
} }

View File

@ -135,26 +135,23 @@ export default class ContentQueryWebPart
viewFields: this.properties.viewFields, viewFields: this.properties.viewFields,
}; };
// Enable MGT support if provider isn't registered and we requested MGT support // Enable MGT support only if required
// if (this.properties.enableMGT && Providers.globalProvider === undefined) {
// Providers.globalProvider = new SharePointProvider(this.context);
// }
if (this.properties.enableMGT) if (this.properties.enableMGT)
{ {
// Add MGT dependencies
const MGT:any = require('@microsoft/mgt'); const MGT:any = require('@microsoft/mgt');
// We only need to re-register the SharePoint provider if we didn't register it before
if (MGT.Providers.globalProvider === undefined) { if (MGT.Providers.globalProvider === undefined) {
// Register the SharePoint provider
MGT.Providers.globalProvider = new MGT.SharePointProvider(this.context); MGT.Providers.globalProvider = new MGT.SharePointProvider(this.context);
} }
// if (this.properties.enableMGT === undefined) { // Make sure that the custom binding syntax is enabled
// this.properties.enableMGT = false; // we do this because we don't want the standard MGT template binding ( {{ }} ) to interfere with handlebars syntax
// }
MGT.TemplateHelper.setBindingSyntax('[[', ']]'); MGT.TemplateHelper.setBindingSyntax('[[', ']]');
} }
const element: React.ReactElement<IContentQueryProps> = React.createElement(ContentQuery, const element: React.ReactElement<IContentQueryProps> = React.createElement(ContentQuery,
{ {
onLoadTemplate: this.loadTemplate.bind(this), onLoadTemplate: this.loadTemplate.bind(this),