Persist View State

O presente artigo destina-se a explicar o funcionamento da preservação do estado da view, isto é, preservar o conjunto de interações realizadas pelo utilizador sobre uma view.

Overview

Para melhorar a experiência de utilização da aplicação, foi criado um mecanismo que permite guardar qual é o campo da view em que o utilizador está a trabalhar e, sempre que exista um acesso posterior a essa view, a aplicação irá redirecionar para esse campo no seu carregamento. Este redireccionamento tem em conta qual os expanders abertos, extender escolhida e linha da grelha selecionada.

Cada view state é associado a um determinado draft de uma determinada subscrição. Uma subscrição pode ter um conjunto infinito de estados desde que exista o mesmo número de drafts criados.

O view state é preservado utilizando o tipo de cache sessionCache, o que significa que apenas é mantida enquanto a sessão do browser existir tenha sido feito um refresh à página, fecho da tab, janela ou fecho do browser.

Arquitetura

Os principais componentes existentes são:

  • ViewState: Estrutura que permite definir o estado de uma view.
  • ViewStateStack: Estrutura que oferece uma API que permite a manipulação de um conjunto de ViewState. Implementa a interface ICacheble fazendo um contrato com os serviços de cache para assim, poder ser armazenada.
  • ViewStatePersistService: Serviço responsável por preservar o estado de uma view. É utilizada por todos os componentes que queiram notificar e armazenar alterações ao estado da view.

Diagrama de classes

Segue-se o diagrama de class simplificado, onde mostra as relações entre os vários componentes pertencentes à preservação do estado da view, bem como todos aqueles que interagem com estes componentes. Os componentes cujo a sua cor de fundo está a cinzenta, são os componentes principais à preservação do estado da view e os restantes são aqueles que utilizam estes para dizerem que ações foram feitas ao estado da view:

ViewState class

A class ViewState disponibiliza os seguintes atributos:

/* 
* Class that represents a state of the view
*/
export class ViewState { 
    /** Id of the draft that the view state is associated with  */
    draftId: string;
    /** DOM Id element which the view is focus  */
    domElementId: string;
    /** Index line in case of the dom element is inside of a grid */
    gridLineIndex: number;
    /** List of expanders that are open  */
    openedExpanders: Array<string>;
    /** Extension Id that is visible  */
    extensionId: string;
    /** Grid Id in case of the dom element is inside of a grid  */
    gridId: string;
}

Serviço ViewStatePercisteService

O serviço ViewStatePercisteService oferece a seguinte API:

/**
 * Service responsible to persiste a view state
 */
@Injectable()
export class ViewStatePersisteService {
    /** 
     * Adds a new view state 
     * @param viewState Object that represents the view state
     */
    add(viewState: ViewState) : void;

    /** 
     * Adds or sets (if exists) a new focus dom element id
     * @param viewState Object that represents the view state
     * @param domElementId DOM Id element which the view is focus
     */
    addOrSetDomElement(draftId: string, domElementId: string): void;

    /** 
     * Adds or sets (if exists) a new focus grid line index
     * @param draftId Id of the draft that the view state is associated with
     * @param gridLineIndex Index line in case of the dom element is inside of a grid
     */
    addOrSetGridLineIndex(draftId: string, gridLineIndex: number): void;

    /** 
     * Adds or sets (if exists) a new focus grid id
     * @param draftId Id of the draft that the view state is associated with
     * @param gridId Grid Id in case of the dom element is inside of a grid
     */
    addOrSetGridId(draftId: string, gridId: string): void;

    /** 
     * Adds or sets (if exists) a new focus grid id
     * @param draftId Id of the draft that the view state is associated with
     * @param extensionId Extension Id that is visible
     */
    addOrSetExtensionSelected(draftId: string, extensionId:string): void;

    /** 
     * Adds or sets (if exists) a new view state
     * @param viewState Object that represents the view state
     */
    addOrSet(viewState: ViewState): void;

    /** 
     * Gets a viewstate from the view state stack
     * @param draftId Id of the draft that the view state is associated with
     * @param removeNode flag that allows to remove the node if exists
     */
    get(draftId: string, removeNode: boolean = false): ViewState;

    /** 
     * Removes a viewstate from the view state stack
     * @param draftId Id of the draft that the view state is associated with
     */
    remove(drafID: string): void;

    /** 
     * Sets a viewstate from the view state stack
     * @param viewState Object that represents the view state
     */
    set(viewState: ViewState): void;

    /** 
     * Adds a new open expander to a view state
     * @param draftId Id of the draft that the view state is associated with
     * @param expanderId Id of the expander that is opened
     */
    addOpenedExpander(draftId: string, expanderId: string): void;

    /** 
     * Removes a new open expander to a view state
     * @param draftId Id of the draft that the view state is associated with
     * @param expanderId Id of the expander that is opened
     */
    removeOpenedExpander(draftId: string, expanderId: string): Boolean;

    /**
     * Verifies if the view state exists
     * @param draftId Id of the draft that the view state is associated with 
     */
    exists(draftId: string): boolean;

}

Pedido de um estado de view preservado

Segue-se o diagrama de sequências de um pedido de estado de view:


Nota: Para mais informações à cerca de como funciona os serviços de cache, bem como a forma correta de os implementar, aceda aqui.

@Author: Ricardo Rocha (ricardo.rocha@primaverabss.com)`