Disable unselection in sketchviewmodel

1632
6
Jump to solution
12-06-2019 07:00 AM
ae
by
Occasional Contributor II

Hi, 

I'm using sketchviewmodel to build a custom editing experience.

In my application I want to force the user to only update a single graphic. It should not be possible to click outside the graphic to cancel/complete the update operation. Unfortunately I cannot seem to disable the behaviour where a graphic is unselected when the user clicks outside the graphic. I've tried listening to the click event on the mapview and calling stopPropagation, but that doesn't seem to have an effect as the graphic is still unselected when I click outside it.

Does anyone know a way to disable the cancel/complete events that fires when clicking outside a graphic that is being updated using the sketchviewmodel? 

0 Kudos
1 Solution

Accepted Solutions
FreddyBroring
New Contributor III
public startEdit() {
    this.history = null;
    this.updateHandle = this.sketchViewModel.on('update', this.onGraphicUpdate.bind(this));
}

private onGraphicUpdate(event) {
    const graphic: __esri.Graphic = event.graphics[0];

    if (event.state === 'complete' || event.state === 'cancel') {
       this.sketchViewModel.update([graphic], {
          tool: 'reshape',
       });
       return;
    }
 }

This should work (notice that this is Typescript). 

If you want to take the undo stack to the newly started update session you have to do some hacking on the sketchViewModel and save the history (not recommended):

public startEdit() {
    this.updateHandle = this.sketchViewModel.on('update', this.onGraphicUpdate.bind(this));
}

private onGraphicUpdate(event) {
    const graphic: __esri.Graphic = event.graphics[0];

    if (event.state === 'complete') {
        this.sketchViewModel.update([graphic], {
            tool: 'reshape',
        });

        if (this.history && (this.sketchViewModel as any)._operationHandle) {
            (this.sketchViewModel as any)._operationHandle.history = this.history;
        }
        return;
    }

    this.history = (this.sketchViewModel as any)._operationHandle.history;
}

 (hope Esri will support this in a future release):

View solution in original post

0 Kudos
6 Replies
Noah-Sager
Esri Regular Contributor

Does something like this help?

Sketch update validation | ArcGIS API for JavaScript 4.13 

It limits the actions and extent of updates using the SketchViewModel.

0 Kudos
ae
by
Occasional Contributor II

Hi, thanks for the reply. That helps as I am able to re-trigger the update operation if the user clicks outside the feature. However, the undo/redo stack is lost when this happens, which is a pity. 

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there, 

That is because, the sample is calling sketchViewModel.update method if user clicks outside of the graphic. You can just return when this happens that way you will not use your undo/redo stack. Calling sketchViewMode.update resets the undo/redo stack.

else if (event.state === "cancel" || event.state === "complete") {
 if (!contains || intersects) {
   return;
   // sketchViewModel.update([graphic], { tool: "reshape" });
 }
}
ae
by
Occasional Contributor II

I tried your suggestion Undral but I cannot get it to work. If I edit the example to just return: 

else if (event.state === "cancel" || event.state === "complete") {
    if (!contains || intersects) {
       return;
    }‍‍‍‍
}

and then click outside the graphic that is being updated, the graphic looses its editing focus and the undo/redo stack is lost. What I want to achieve is to keep the editing focus on the graphic despite clicking outside the graphic, and at the same time keep the undo/redo stack.

Perhaps I'm missing something. It would be great if you could provide a small example. 

0 Kudos
FreddyBroring
New Contributor III
public startEdit() {
    this.history = null;
    this.updateHandle = this.sketchViewModel.on('update', this.onGraphicUpdate.bind(this));
}

private onGraphicUpdate(event) {
    const graphic: __esri.Graphic = event.graphics[0];

    if (event.state === 'complete' || event.state === 'cancel') {
       this.sketchViewModel.update([graphic], {
          tool: 'reshape',
       });
       return;
    }
 }

This should work (notice that this is Typescript). 

If you want to take the undo stack to the newly started update session you have to do some hacking on the sketchViewModel and save the history (not recommended):

public startEdit() {
    this.updateHandle = this.sketchViewModel.on('update', this.onGraphicUpdate.bind(this));
}

private onGraphicUpdate(event) {
    const graphic: __esri.Graphic = event.graphics[0];

    if (event.state === 'complete') {
        this.sketchViewModel.update([graphic], {
            tool: 'reshape',
        });

        if (this.history && (this.sketchViewModel as any)._operationHandle) {
            (this.sketchViewModel as any)._operationHandle.history = this.history;
        }
        return;
    }

    this.history = (this.sketchViewModel as any)._operationHandle.history;
}

 (hope Esri will support this in a future release):
0 Kudos
ae
by
Occasional Contributor II

Many thanks for the example Freddy. I will re-trigger update as you suggest and skip hacking the sketchviewmodel in case it has some unwanted side-effects. I too hope esri will add this functionality.