Advertisement

#29 Adding A New Accounts Details View For Editing And Creating Accounts

In this article we will focus on creating a new accounts details page which will allow us to create and edit accounts. We will start by adding the ability to route to the new page using our routing system. Along the way we will make a few updates to a couple of our previously created types so that their names will be inline with the conventions we have developed. We will then finish up by using the infrastructure that we have developed along the way to quickly add some basic functionality to our newly created details view.

Code Snippets

AccountsDetails.vue (1:29)

<template lang="pug">
div accounts details
</template>
src ⟩ views ⟩ AccountsDetails.vue

AccountsDetails.vue (1:29)

<script lang="tsx">
import { Component, Vue } from "vue-property-decorator";

@Component
export default class AccountsDetails extends Vue {
    
}
</script>
src ⟩ views ⟩ AccountsDetails.vue

types.ts (1:55)

...
export enum Routes {
    ...
    AccountsDetails,
    ...
}
...
src ⟩ components ⟩ routing ⟩ types.ts

routing-service.ts (2:07)

...
const accountsDetails = new RouteEntry({
    component: () => import(/* webpackChunkName: "accounts-details" */ "../../views/AccountsDetails.vue"),
    name: "accounts-details",
    parent: accounts,
    path: "/accounts-details",
    route: Routes.AccountsDetails,
});
...
export class RoutingService {
    ...
    private readonly _routes = [..., accountsDetails, ...];
    ...
}
src ⟩ components ⟩ routing ⟩ routing-service.ts

Accounts.vue (3:06)

<script lang="tsx">
...
export default class Accounts extends Vue {
    ...
    private onClick(account: AccountModel) {
        this.routingService.navigateTo(Routes.AccountsDetails, {
            query: { id: `${account.id}` },
        });
    }

    private onClickCreate() {
        this.routingService.navigateTo(Routes.AccountsDetails, {
            query: { id: "0" },
        });
    }
    ...
}
</script>
src ⟩ views ⟩ Accounts.vue

route-types.ts (4:59)

...
export type PayloadPopRoute = void;
export type PayloadPushRoute = IRoute;
src ⟩ store ⟩ route-types.ts

route-module.ts

...
import { PayloadPushRoute } from "@/store/route-types";
...
export const routeActions: StoreActionTree = {
    ...,
    [ACTION_PUSH_ROUTE](this, { commit }, route: PayloadPushRoute) {
        ...
    },
};

export const routeMutations: StoreMutationTree = {
    ...,
    [MUTATION_PUSH_ROUTE](state: IStoreState, payload: PayloadPushRoute) {
        ...
    },
};
...
src ⟩ store ⟩ route-module.ts

Advertisement

TheRouterOutlet.vue (5:49)

<script lang="ts">
...
import { ..., PayloadPopRoute, PayloadPushRoute } from "@/store";
...
export default class TheRouterOutlet extends Vue {
    @Action(ACTION_POP_ROUTE) private readonly popRoute!: ActionFn<PayloadPopRoute>;
    @Action(ACTION_PUSH_ROUTE) private readonly pushRoute!: ActionFn<PayloadPushRoute>;
    ...
}
</script>
src ⟩ components ⟩ routing ⟩ TheRouterOutlet.vue

SecuritiesDetails.vue (6:22)

<script lang="ts">
...
import {
    ...,
    PayloadPushRoute,
    ...,
} from "@/store";
...
export default class SecuritiesDetails extends Vue {
    ...
    @Action(ACTION_PUSH_ROUTE) private readonly pushRoute!: ActionFn<PayloadPushRoute>;
    ...
}
</script>
src ⟩ views ⟩ SecuritiesDetails.vue

routing-service.ts (7:16)

...
export class RoutingService {
    ...
    public isPreviousRoute = (route: Routes) => {
        if (this.history.length === 0) {
            return false;
        }
        return this.history[0].id === route;
    };
    ...
}
src ⟩ components ⟩ routing ⟩ routing-service.ts

AccountsDetails.vue (8:19)

<script lang="tsx">
import { ..., Inject, ... } from "vue-property-decorator";

import DetailsActionButtons from "@/components/DetailsActionButtons.vue";
import { Routes, RoutingService } from "@/components/routing";

import { ACTION_PUSH_ROUTE, Action, ActionFn, GETTER_ACCOUNT, Getter, GetterAccount, PayloadPushRoute } from "@/store";

interface IQuery {
    id: string;
}

@Component({
    components: {
        DetailsActionButtons,
    }
})
export default class AccountsDetails extends Vue {
    @Action(ACTION_PUSH_ROUTE) private readonly pushRoute!: ActionFn<PayloadPushRoute>;
    @Getter(GETTER_ACCOUNT) private readonly getterAccount!: GetterAccount;
    @Inject() private readonly routingService!: RoutingService;

    private id = 0;
    private name = "";

    private created() {
        if (this.routingService.isPreviousRoute(Routes.Accounts) === false) {
            this.pushRoute(this.routingService.createRoute(Routes.Accounts));
        }

        this.id = this.routingService.queryParam<IQuery, number>((x) => x.id, parseInt);

        if (this.id <= 0) {
            return;
        }

        this.load();
    }

    private load() {
        const account = this.getterAccount(this.id);
        this.name = account.name;
    }

    private save() {
        console.log("save");
    }
}
</script>
src ⟩ views ⟩ AccountsDetails.vue

AccountsDetails.vue (13:15)

<template lang="pug">
div
    form
        div.inputs
            h1 Account Details
            label Name
            input(
                type="text"
                v-model="name")
        DetailsActionButtons(v-bind:save="save")/
</template>
src ⟩ views ⟩ AccountsDetails.vue

AccountsDetails.vue

<style lang="sass" scoped>
@import "../bourbon/bourbon"
@import "../bitters/functions"
@import "../bitters/variables"

.inputs
    @include padding(null 0.25rem)
</style>
src ⟩ views ⟩ AccountsDetails.vue

Exciton Interactive LLC
Advertisement