SpringBot CRUD Tile Customisation of Post Creation

By default, SpringBot redirects a user back to the CRUD list upon successful persistence of an entity. In certain circumstances, this is not desired and as such the redirect can be customised to be dynamic based on the submitted data.


Model

Fishnatics Model

For this article we will be using our Fishnatics entity model as our example. Specifically our ‘Tank’ entity.

The current behaviour redirects the users back to the CRUD list as shown below upon successful persistence.

Current Behaviour

Task

In this article we will be stepping through the process of adding custom actions upon the successful creation of an entity instance in the CRUD tile.

AdminTankTileCrudComponent::onCreateOrSaveClicked

The first method we will explore is the onCreateOrSaveClicked found within clientside/src/app/admin/tiles/crud/tank/tank.admin.tile.crud.component.ts.

This method is triggered when the save button is clicked within the create/update view of the CRUD tile and manages the persistence of the data.

Within this method, there are a couple of important elements.

TargetModel

The target model contains all the data for the model which is being saved/updated.

This is accessible through the use of this.targetModel. Placing a debugger breakpoint here we can see this.

Target Model

Persistence

As mentioned before, this method controls the persistance of the updated targetModel. This is achieved through the use of an NgRx action.

This method controls both the creation and update actions and these are treated differently based on the condition event.isCreate.

The state is first set with the target model data. We can modify out state before persisting in the protected region here called Add any additional onCreateOrSaveClicked logic before the main body here.

let stateConfig: PassableStateConfig<TankModel> = {
    targetModel: this.targetModel,
    queryParams: this.queryParams,
    collectionId: this.collectionId
};

Before the event is then triggered, the after action list is set; this list of actions includes a redirect to the CRUD list page.

let afterwardActions: NgRxAction[] = [
    new routingAction.NavigateRoutingAction(['admin', 'entities', 'tank'])
];

To override this default action turn on the protected region called Add any additional logic before creating a new model here and place your new actions in here.

For example, to route back to the home page after save, you would add the following:

// % protected region % [Add any additional logic before creating a new model here] on begin
afterwardActions = [
    new routingAction.NavigateRoutingAction(['home'])
];
// % protected region % [Add any additional logic before creating a new model here] end

One issue you will note here is we have access to the pre-persistance state, but not anything that may be returned from the server for this action.

We will look at actions pertaining to data from the server in a moment.

Now, after all actions have been defined, the CreateTankModel action is dispatched.

this.store.dispatch(new modelAction.CreateTankModel(
    stateConfig,
    // % protected region % [Add any additional constructor arguments for CreateModel here] off begin
    // % protected region % [Add any additional constructor arguments for CreateModel here] end,
    afterwardActions
));
Post Save

Some actions may require updated state from the server to execute. The NavigationAction built into SpringBot is stateless in so much, that it is unaware of the state of the current model.

To achieve state aware routing, we will need to create a new action.

  1. Open the file called tank.model.action.ts found at clientside/src/app/models/tank/tank.model.action.ts. Find and activate the protected region called Add any additional model actions here.
  2. Add the following:

    // % protected region % [Add any additional model actions here] on begin
     STATE_AWARE_POST_SAVE_REDIRECT = '[ENTITY] Redirected successfully'
     // % protected region % [Add any additional model actions here] end
    
  3. Find and activate the protected region called Add any additional actions here.
  4. Add the following:

    export class StateAwareRoutingAction extends BaseTankAction {
        
     readonly type: string = TankModelActionTypes.STATE_AWARE_POST_SAVE_REDIRECT;
        
     public constructor(
         public readonly stateConfig: PassableStateConfig<TankModel>,\
             public readonly extras: NavigationExtras = { skipLocationChange: false },
             public readonly commands: any[],
             afterwardActions: Action[] = []
         ) {
             super(
                 afterwardActions
             );
         }
     }
    
  5. Open the the tank.model.effect.ts file found atclientside/src/app/models/tank/tank.model.effect.ts and find the protected region labelled Add any additional imports here and activate it.
  6. Add the following:

    // % protected region % [Add any additional imports here] on begin
     import { Router } from '@angular/router';
     import { tap } from 'rxjs/operators';
     // % protected region % [Add any additional imports here] end
    
  7. We now need to ensure that the target model data can be passed to our new action. Find the protected region called Add any additional constructor arguments for CreateModelOK here and activate it.
  8. Add the following:

    // % protected region % [Add any additional constructor arguments for CreateModelOK here] on begin
     action.afterwardActions.map(afterwardAction => {
         if (afterwardAction instanceof modelAction.StateAwareRoutingAction) {
             return new modelAction.StateAwareRoutingAction({
                 ...action.stateConfig,
                 ...stateConfig
             }, afterwardAction.commands, afterwardAction.extras)
         } else {
             return afterwardAction;
         }
     }),
     // % protected region % [Add any additional constructor arguments for CreateModelOK here] end
    

    This will ensure that the correct data is passed down to your new action after the create action is complete.

    **NOTE**: This protected region will be released with SpringBot version 1.2.1.0
    
  9. Now to create the effect for your new action. Find the protected region called Add any additional class methods here and activate it.
  10. Add the following:

    @Effect({ dispatch: false })
     stateAwareRedirect = this.action$.pipe(
         ofType<modelAction.StateAwareRoutingAction>(modelAction.TankModelActionTypes.STATE_AWARE_POST_SAVE_REDIRECT),
        
         tap((action) => {
             const targetModel = (action as modelAction.StateAwareRoutingAction).stateConfig.targetModel;
             let commands = (action as modelAction.StateAwareRoutingAction).commands;
             let extras = (action as modelAction.StateAwareRoutingAction).extras;
        
             // Execute any commands
             const executedCommands = commands.map(command => {
                 if (command instanceof Function) {
                     return command(targetModel);
                 } else {
                     return command;
                 }
             });
             this.router.navigate(executedCommands, extras);
         })
     );
    
  11. Our final step is to add this action to our afterwardsActions. Open tank.admin.tile.crud.component.ts found at clientside/src/app/admin/tiles/crud/tank/tank.admin.tile.crud.component.ts and find the protected region called Add any additional logic before creating a new model here and activate it.
  12. Add the following:

    afterwardActions = [
         new modelAction.StateAwareRoutingAction(stateConfig,
                     ['admin', 'entities', 'tank', 'edit', (targetModel: TankModel) => targetModel.id])
     ];
    

    This will cause your application to route to edit page for the Tank entity you just created.

    i.e. http://localhost:4200/admin/entities/tank/edit/821a81a3-a780-4e8e-9ca7-8bcd13d824cf

Last updated: 04 June 2020


Start modelling your app today.