This is an test webpart root workspace of a SharePoint MVC implementation using PNPjs, Classtransformer, MobX, Spfx-Controls and Fluent UI.
It's purpose is to test and showcase the technical state of the reusable hybrid repo mvc spfx examples:
- clean invisible object state management with MobX
- the webpart has no reference to Mobx it only deals with the data objects
- all MobX use in the shared libraries
- state of the Views, fields and form
- access to a list on a different site
- starting point for webparts accessing lists on different sites
focus on business logic development
You can use the "Minimal path to awesomeness" to have look around. Please branch before contributing. You can follow the "Create a new project" to start with a copy of this a starting point for a new project (usually app)
You should have the following installed:
- A code editor
- Node 14
- yarn
- git
- GitExtension (the program, if your contributing or forking a new project of this)
- access to a SharePoint site with lists
The lists are selected in the webpart configuration. They need to match the models in the app.
Edit properties of the models to match your lists. As example:
export class TestList1 extends ListItem {
public constructor() {
super();
}
@Expose({ name: 'CustomText'})
public customText: string;
...
@Type( () => ListItemBase )
@Expose({ name: 'SingleLookup' })
public singleLookup: ListItemBase;
}
Extending from ListItem
makes it on observable SharewPoint object.
It inherits properties like author
, contentTypeId
, ... The SharePoint
- internal fieldname
CustomText
is transformed to the propertycustomText
. singleLookup
is usingListItemBase
as a lookup to Title and Id.
The Announcements
list can be located on a different site.
git clone --recurse-submodules https://github.com/mauriora/WebPart-Test-Workspaces.git
cd WebPart-Test-Workspaces
yarn
code .
open a terminal in the solution (root) folder
The node_modules
folder in the solution should contain the majority of dependencies, while the node_modules
folder of each sub modules should only contain very few dependencies if any.
All modules in shared
should be linked in the solutions node_modules
folder.
yarn build-shared
yarn serve
browse to the workbench on YOUR-SITE add the webpart to the page
- In a solution terminal execute
yarn workspace @mauriora/webpart-test serve
- browse to the sharepoint app store on YOUR-TENANT
- Click Upload
- Click Choose files
- Navigate to YOUR-SOLUTION/apps/YOUR-PROJECT/sharepoint/solution
- Select YOUR-PROJECT.sppkg and click Open
- Add a comment and click OK
- Wait for the upload to finish and a dialog to open
- If you want the webpart to be available on all sites without installing, tick Make this solution available to all sites in the organization, otherwise it needs to be installed on each site using
- Click Deploy
- grant API permissions in Sharepoint Admin Center: Advanced / API access
- If not installed tenant wide, go to each site you wnat the webpart on
- Go to Site Content
- Click + New -> App
- Find YOUR-APP and click on it
- Wait until it's installed
- Create a page and add YOUR-WEBPART
The webpart displays two list from different sites to demonstrate cross site access:
return <Stack>
<ListAndForm
key={'ListAndForm-local'}
dataClass={TestList1}
siteUrl={localSiteUrl}
listId={localListId}
/>
<ListAndForm
key={'ListAndForm-isolated'}
dataClass={Announcement}
siteUrl={isolatedSiteUrl}
listId={isolatedListId}
/>
</Stack>;
Each ListAndForm contains a list with two forms next to each other. Each form showing the same object:
return <Stack>
<ItemsList model={model} onSelect={onSelect} />
<Stack horizontal>
<ItemForm
key={listId + '-form1'}
model={model}
item={item}
... />
<ItemForm
key={listId + '-form2'}
model={model}
item={item}
... />
</Stack>
</Stack>;
No explicit event handler exists between the forms.
a modification to the item[property]
in either form is instantly reflected in the other form. Here the example of the boolean field:
export const BooleanField: PropertyFieldFC = observer(({ info, item, property }) => {
const value = item[property];
if(undefined !== value && typeof value !== 'boolean') throw new Error(...);
return <Checkbox
label={info.Title}
checked={value}
disabled={info.ReadOnlyField}
onChange={(e, checked) => item[property] = checked}
/>
});
observer
is mobX rendering the checkbox when the observable property
in the observable item
changes. item
is is an instance of your model. All properties in the modules are automatically observable. For the observer
to work, the property needs to be accessed in side the observer.
The info
object comes from the SharePoint model being a IFieldInfo
, e.g. info.Title` is the diplayname.
Use the minmal path to awesomeness and please create a branch and fork for your contribution. Then do a pull request to merge your branch into the main branch.
- Fork the solution as YOUR-SOLUTION
- Clone the forked solution
- Fork the starting app project as YOUR-PROJECT
- Add the YOUR-PROJECT as submodule to YOUR-SOLUTION using the app GitExtenson, manage sub modules
- Remove the starting project, and any other you don't need, from YOUR-solution using the app GitExtenson, manage sub modules
- call
yarn initguids
in apps/YOUR-PROJECT - rename YOUR-..... in:
- app/YOUR-PROJECT
- packgae.json
- src/webparts/YOUR-WEBPART
- YOUR-WEBPART.manifest.json
- config
- config.json
- package-solution.json
- app/YOUR-PROJECT
- Create a new repository with at least one file (e.g. default README.md)
- Copy the clone URL to the clipboard
- Open Git-Extension
- Open the solution
- Open the menu
Repository
and selectManage submodules...
- Click
Add submodule
- Paste the URL from the clipboard into
Path to submodule
- Prefix the local path with either
app/
orshared/
- Select the appropiate branch, e.g.
main
- Click
Add
- edit the
package.json
to have a qualified package name - In a solution folder terminal execute:
yarn clean-node-modules
lerna bootstrap