Domanda

Im working on a pretty simple spfx CommandSet extension. Its goal is to duplicate an item, when an item is selected. I have the working code. My problem is, that i searched the context property, but could not find a method, to update the ListView, to show the newly created(duplicated) item. (By default it not shows the created item because i created it with an API call)

Code:

@override
public onListViewUpdated(event: IListViewCommandSetListViewUpdatedParameters): void {
  const duplicateCommand: Command = this.tryGetCommand('DUPLICATE_ITEM');
  if (duplicateCommand) {
    duplicateCommand.visible = (event.selectedRows.length === 1);
  }
}

@override
public onExecute(event: IListViewCommandSetExecuteEventParameters): void {
  switch (event.itemId) {
    case 'DUPLICATE_ITEM': this.DuplicateItem(event); break;
    default: throw new Error('Unknown command');
  }
}
private DuplicateItem(event: IListViewCommandSetExecuteEventParameters): void {
  //stuff to do
  pnp.sp.web.lists.getByTitle(listName).items.add(data)
    .then((result: any) => {
      //refresh ListView to show new item
    }).catch(error => {
      //error handling
    });
}

How can i do this?

È stato utile?

Soluzione

There is a Microsoft sample project on github that does exactly the same. Looking at their code, it does mention that there is currently no way to refresh just the list view and their solution seems to be reloading the entire page using location.reload();. If you look at the file SpfxCloneCommandSet.ts they mention that there is currently no way to reload just the list view and just refresh entire page.

Altri suggerimenti

Unfortunately, you cannot update a list view with the help of user API without refreshing the whole page. But it is possible to extract corresponding method from a built-in require module with the below code:

var listEl = document.querySelector('.sp-App-root');
var listVM = __ko.dataFor(listEl);
var ii = listVM.resources.consume(require.s.contexts._.defined.eR.itemInvalidator);
ii.invalidateCurrentItemSet();

Since the module containing the 'itemValidator' can be renamed in future updates of SharePoint, I optimized the above by iterating through all loaded modules and checking whether the 'itemInvalidator' property exists:

var modules = window.require.s.contexts._.defined;
for (var p in modules) {
    if (modules.hasOwnProperty(p) && modules[p] && modules[p].itemInvalidator) {
        var itemInvalidatorKey = modules[p].itemInvalidator;
        var rootEl = document.getElementById('appRoot');
        var rootVM = window.__ko.dataFor(rootEl);
        var itemInvalidator = rootVM.resources.consume(itemInvalidatorKey);
        itemInvalidator.invalidateCurrentItemSet()
        break;
    }
}

Please check out this workaround which is working for me:

 public static forceListViewUpdate() {

    try {
      let modules = (window as any).require.s.contexts._.defined;
      for (var p in modules) {
        if (modules.hasOwnProperty(p) && modules[p] && modules[p].itemInvalidator) {
          let itemInvalidatorKey = modules[p].itemInvalidator;
          let rootEl = document.getElementById('appRoot');
          let rootVM = (window as any).__ko.dataFor(rootEl);
          let itemInvalidator = rootVM.resources.consume(itemInvalidatorKey);
          itemInvalidator.invalidateCurrentItemSet();
          break;
        }
      }
    } catch (e) {
      console.log('Unable to update ListView:', e);
    }

      }

If you like, check the source here.

I know it's old question but I got here looking for an answer so I'll put what I found here. My answer applies to SharePoint 2019 On Premise and is based on @Alberto and @Dmitry Kozlov answers:

var key = Object.keys(odstore.dataStore)[0].substr("item=".length);
var rootEl = document.getElementById('appRoot');
var rootVM = window.__ko.dataFor(rootEl);
var modules = window['require']['s'].contexts._.defined;
var itemProviderModule = modules["odsp-next/providers/item/ItemProvider"];
var itemProvider = rootVM.resources.consume(itemProviderModule.resourceKey);
itemProvider.invalidateItem(key, {triggerFetch: true});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a sharepoint.stackexchange
scroll top