Advertisement

#41 Display Plans Using JSX And Create A Plan Details View

In this article we will use the list view component that we created previously and some JSX to display the names of the portfolio plans that are saved within our vuex store. Once that is done we will proceed to add the capability to view and edit the details of a plan including its name and the percentages of the categories of that plan.

Code Snippets

PlannerDetails.vue (1:54)

<template lang="pug">
div planner details
</template>
src ⟩ views ⟩ PlannerDetails.vue

types.ts (2:18)

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

routing-service.ts (2:34)

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

Planner.vue (3:37)

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

import ListView from "@/components/ListView.vue";
import { IRoute, Routes, RoutingService } from "@/components/routing";
...
@Component({
    components: {
        ListView,
    },
})
export default class Planner extends Vue {
    ...
    @Inject() private readonly routingService!: RoutingService;

    private onClick(plan: PortfolioPlanModel) {
        this.routingService.navigateTo(Routes.PlannerDetails, {
            query: { id: `${plan.id}`},
        });
    }

    private onClickCreate() {
        this.routingService.navigateTo(Routes.PlannerDetails, {
            query: { id: "0"},
        });
    }

    private renderPlan(plan: PortfolioPlanModel) {
        return <label>{plan.name}</label>
    }
}
</script>
src ⟩ views ⟩ Planner.vue

Planner.vue (7:00)

<template lang="pug">
ListView(
    v-bind:items="plans"
    v-bind:onClick="onClick"
    v-bind:onClickCreate="onClickCreate"
    v-bind:renderFn="renderPlan")
</template>
src ⟩ views ⟩ Planner.vue

Advertisement

PlannerDetails.vue (8:22)

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

import { Routes, RoutingService } from "@/components/routing";
import { ACTION_PUSH_ROUTE, Action, ActionFn, PayloadPushRoute } from "@/store";

interface IQuery {
    id: string;
}

@Component
export default class PlannerDetails extends Vue {
    @Action(ACTION_PUSH_ROUTE) private readonly pushRoute!: ActionFn<PayloadPushRoute>;
    @Inject() private readonly routingService!: RoutingService;

    private id = 0;

    private load() {
        console.log("loading");
    }

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

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

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

        this.load();
    }
}
</script>
src ⟩ views ⟩ PlannerDetails.vue

PlannerDetails.vue (12:39)

<script lang="ts">
...
import DetailsActionButtons from "@/components/DetailsActionButtons.vue";
...
import {
    ...
    GETTER_PORTFOLIO_PLAN,
    Getter,
    GetterPortfolioPlan,
    ...
    PortfolioCategoryModel,
} from "@/store";
...
@Component({
    components: {
        DetailsActionButtons,
    },
})
export default class PlannerDetails extends Vue {
    ...
    @Getter(GETTER_PORTFOLIO_PLAN) private readonly getterPlan!: GetterPortfolioPlan;
    ...
    private portfolioCategories: PortfolioCategoryModel[] = [];
    ...
    private name = "";

    private load() {
        const plan = this.getterPlan(this.id);
        this.name = plan.name;
        this.portfolioCategories = plan.categories;
    }
    ...
    private save() {
        console.log(this.portfolioCategories);
    }
}
</script>
src ⟩ views ⟩ PlannerDetails.vue

PlannerDetails.vue (15:18)

<template lang="pug">
form
    div.inputs
        h1 Plan Details
        label Name
        input(v-model="name")
        ul
            li(
                v-for="portfolioCategory in portfolioCategories"
                v-bind:key="portfolioCategory.id")
                label {{portfolioCategory.category.text}}
                input(v-model.number="portfolioCategory.percent")
    DetailsActionButtons(v-bind:save="save")/
</template>
src ⟩ views ⟩ PlannerDetails.vue

PlannerDetails.vue (17:26)

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

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

Exciton Interactive LLC
Advertisement