Advertisement

#24 Navigating To The Security Details Page

In this article we will start off by unifying our approach to binding the required properties for the list views that we are using in our securities view. What this means is that we will use a factory method to create the on click handlers for all of the list views instead of special methods for the securities and categories. While we are at it we will also create a factory method for creating new items and we will also bind the results of invoking that method to our list views so that we have the ability to create new items to add to our vuex store. We will then finish up by making a few changes to our securities details view. The first up is a small tweek that will make sure that our routing history always has it's top entry pointing to the securities view page if we are on the details page even if the user refreshes and therefore clears the history. Lastly we will use the getters that we created in a previous article to retrieve the appropriate item from the store when the user clicks on and existing item.

Code Snippets

ListView.vue (1:43)

<script lang="tsx">
...
export default class ListView extends Vue {
    ...
    @Prop() private readonly onClickCreate!: () => void;
    ...
    private render() {
        ...
        return (
            <ul>
                { this.onClickCreate &&
                    <li>
                        <a class="list-item-content create" href="#void" onClick={() => this.onClickCreate()}>
                            <div class="list-item-text">Create</div>
                            <span>&#43;</span>
                        </a>
                    </li>
                }
                ...
            </ul>
        );
    }
}
</script>
src ⟩ components ⟩ ListView.vue

types.ts (4:18)

export enum SecurityDescriptors {
    Categories,
    Markets,
    None,
    Securities,
    Segments,
    Territories,
    Types,
}
src ⟩ views ⟩ types.ts

Securities.vue (5:12)

<script lang="tsx">
...
import { SecurityDescriptors } from "@/views/types";
...
export default class Securities extends Vue {
    ...
    private readonly descriptorCategories = SecurityDescriptors.Categories;
    private readonly descriptorMarkets = SecurityDescriptors.Markets;
    private readonly descriptorSecurities = SecurityDescriptors.Securities;
    private readonly descriptorSegments = SecurityDescriptors.Segments;
    private readonly descriptorTerritories = SecurityDescriptors.Territories;
    private readonly descriptorTypes = SecurityDescriptors.Types;
    ...
    private onClickCreateFactory(which: SecurityDescriptors) {
        return () => {
            console.log(`${SecurityDescriptors[which]}`);
        };
    }

    private onClickFactory(which: SecurityDescriptors) {
        return (descriptor: SecurityModel | SecurityCategoryModel | SecurityDescriptor) => {
            console.log(`${SecurityDescriptors[which]} ${descriptor.id}`);
        };
    }
    ...
}
</script>
src ⟩ views ⟩ Securities.vue

Securities.vue (8:03)

<template lang="pug">
TabContainer(v-bind:tabs="tabs")
    ListView(
        ...
        v-bind:onClick="onClickFactory(descriptorSecurities)"
        v-bind:onClickCreate="onClickCreateFactory(descriptorSecurities)"
        ...)/
    ListView(
        ...
        v-bind:onClick="onClickFactory(descriptorCategories)"
        v-bind:onClickCreate="onClickCreateFactory(descriptorCategories)"
        ...)/
    ListView(
        ...
        v-bind:onClick="onClickFactory(descriptorMarkets)"
        v-bind:onClickCreate="onClickCreateFactory(descriptorMarkets)"
        ...)/
    ListView(
        ...
        v-bind:onClick="onClickFactory(descriptorSegments)"
        v-bind:onClickCreate="onClickCreateFactory(descriptorSegments)"
        ...)/
    ListView(
        ...
        v-bind:onClick="onClickFactory(descriptorTerritories)"
        v-bind:onClickCreate="onClickCreateFactory(descriptorTerritories)"
        ...)/
    ListView(
        ...
        v-bind:onClick="onClickFactory(descriptorTypes)"
        v-bind:onClickCreate="onClickCreateFactory(descriptorTypes)"
        ...)/
</template>
src ⟩ views ⟩ Securities.vue

ListView.vue (9:04)

<style lang="sass" scoped>
...
.list-item-content
    ...
    &.create
        background-color: $green
        color: white
        font-weight: 600

        &:hover
            background-color: darken($green, 10%)
    ...
</style>
src ⟩ components ⟩ ListView.vue

Advertisement

Securities.vue (10:26)

<script lang="tsx">
import { ... Inject, ... } from "vue-property-decorator";
...
import {
    IRoute,
    Routes,
    RoutingService,
} from "@/components/routing";
...
export default class Securities extends Vue {
    ...
    @Inject() private readonly routingService!: RoutingService;
    ...
    private onClickCreateFactory(which: SecurityDescriptors) {
        return () => {
            this.routingService.navigateTo(Routes.SecuritiesDetails, {
                query: { id: "0", which: `${which}` },
            });
        };
    }

    private onClickFactory(which: SecurityDescriptors) {
        return (descriptor: SecurityModel | SecurityCategoryModel | SecurityDescriptor) => {
            this.routingService.navigateTo(Routes.SecuritiesDetails, {
                query: { id: `${descriptor.id}`, which: `${which}` },
            });
        };
    }
    ...
}
</script>
src ⟩ views ⟩ Securities.vue

SecuritiesDetails.vue (13:14)

<script lang="ts">
...
import { Routes, ... } from "@/components/routing";

import {
    ACTION_PUSH_ROUTE,
    Action,
    ActionFn,
    IRouteState,
    PushRoutePayload,
    STATE_ROUTES,
    State,
} from "@/store";
...
export default class SecuritiesDetails extends Vue {
    @Action(ACTION_PUSH_ROUTE) private readonly pushRoute!: ActionFn<PushRoutePayload>;
    ...
    @State(STATE_ROUTES) private readonly routeState!: IRouteState;

    private mounted() {
        if (this.routeState.history.length === 0 || this.routeState.history[0].id !== Routes.Securities) {
            this.pushRoute(this.routingService.createRoute(Routes.Securities));
        }
        ...
    }
}
</script>
src ⟩ views ⟩ SecuritiesDetails.vue

SecuritiesDetails.vue (16:14)

<script lang="ts">
...

import {
    ...
    GETTER_SECURITY,
    GETTER_SECURITY_CATEGORY,
    GETTER_SECURITY_MARKET,
    GETTER_SECURITY_SEGMENT,
    GETTER_SECURITY_TERRITORY,
    GETTER_SECURITY_TYPE,
    Getter,
    GetterCategory,
    GetterMarket,
    GetterSecurity,
    GetterSegment,
    GetterTerritory,
    GetterType,
    ...
} from "@/store";
...
import { SecurityDescriptors } from "@/views/types";
...
export default class SecuritiesDetails extends Vue {
    ...
    @Getter(GETTER_SECURITY_CATEGORY) private getterCategory!: GetterCategory;
    @Getter(GETTER_SECURITY_MARKET) private getterMarket!: GetterMarket;
    @Getter(GETTER_SECURITY) private getterSecurity!: GetterSecurity;
    @Getter(GETTER_SECURITY_SEGMENT) private getterSegment!: GetterSegment;
    @Getter(GETTER_SECURITY_TERRITORY) private getterTerritory!: GetterTerritory;
    @Getter(GETTER_SECURITY_TYPE) private getterType!: GetterType;
    ...
    private id = 0;
    private which = SecurityDescriptors.None;

    private mounted() {
        ...
        this.id = this.routingService.queryParam<IQuery, number>((x) => x.id, parseInt);
        this.which = this.routingService.queryParam<IQuery, SecurityDescriptors>((x) => x.which, parseInt);

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

        this.load();
    }

    private load() {
        switch (this.which) {
            case SecurityDescriptors.Categories:
                const category = this.getterCategory(this.id);
                console.log(category.constructor.name);
                return;
            case SecurityDescriptors.Markets:
                const market = this.getterMarket(this.id);
                console.log(market.constructor.name);
                return;
            case SecurityDescriptors.Securities:
                const security = this.getterSecurity(this.id);
                console.log(security.constructor.name);
                return;
            case SecurityDescriptors.Segments:
                const segment = this.getterSegment(this.id);
                console.log(segment.constructor.name);
                return;
            case SecurityDescriptors.Territories:
                const territory = this.getterTerritory(this.id);
                console.log(territory.constructor.name);
                return;
            case SecurityDescriptors.Types:
                const type = this.getterType(this.id);
                console.log(type.constructor.name);
                return;
        }
    }
}
</script>
src ⟩ views ⟩ SecuritiesDetails.vue

Exciton Interactive LLC
Advertisement