bitovi/canjs

View on GitHub
demos/forms/extended-make-model-year.html

Summary

Maintainability
Test Coverage
<my-mmy></my-mmy>

<script src="../../node_modules/steal/steal.js" dev-bundle main="@empty" id="demo-source">
import { ajax, fixture, QueryLogic, StacheElement, type } from "can";

fixture.delay = 1200;

fixture("/makes", fixture.store([
    { id: "1", name: "Ford" },
    { id: "2", name: "Nissan" }
],
{ identity: ["id"] }
));

fixture("/models", fixture.store([
    { id: "1", makeId: "1", name: "Mustang", years: [ 2013, 2014 ] },
    { id: "2", makeId: "1", name: "Focus", years: [ 2013, 2014 ] },
    { id: "3", makeId: "2", name: "Altima", years: [ 2013, 2014 ] },
    { id: "4", makeId: "2", name: "Leaf", years: [ 2013, 2014 ] },
],
{ identity: ["id"] }
));

fixture("/vehicles", fixture.store([
    {id: 1, modelId: "1", year: "2013", name: "2013 Mustang", thumb: "http://mustangsdaily.com/blog/wp-content/uploads/2012/07/01-2013-ford-mustang-gt-review-585x388.jpg"},
    {id: 2, modelId: "1", year: "2014", name: "2014 Mustang", thumb: "http://mustangsdaily.com/blog/wp-content/uploads/2013/03/2014-roush-mustang.jpg"},
    {id: 3, modelId: "2", year: "2013", name: "2013 Focus", thumb: "http://images.newcars.com/images/car-pictures/original/2013-Ford-Focus-Sedan-S-4dr-Sedan-Exterior.png"},
    {id: 4, modelId: "2", year: "2014", name: "2014 Focus", thumb: "http://ipinvite.iperceptions.com/Invitations/survey705/images_V2/top4.jpg"},
    {id: 5, modelId: "3", year: "2013", name: "2013 Altima", thumb: "http://www.blogcdn.com/www.autoblog.com/media/2012/04/04-2013-nissan-altima-1333416664.jpg"},
    {id: 6, modelId: "3", year: "2014", name: "2014 Altima", thumb: "http://www.blogcdn.com/www.autoblog.com/media/2012/04/01-2013-nissan-altima-ny.jpg"},
    {id: 7, modelId: "4", year: "2013", name: "2013 Leaf", thumb: "http://www.blogcdn.com/www.autoblog.com/media/2012/04/01-2013-nissan-altima-ny.jpg"},
    {id: 8, modelId: "4", year: "2014", name: "2014 Leaf", thumb: "http://images.thecarconnection.com/med/2013-nissan-leaf_100414473_m.jpg"},
],
{ identity: ["id"] }
));

class MyMmy extends StacheElement {
    static view  = `
        <select value:bind="this.makeId"
            {{# if(this.makes.isPending) }}disabled{{/ if }}>
            {{# if(this.makes.isPending) }}
              <option value=''>Loading...</option>
            {{ else }}
              {{^ this.makeId }}
                <option value=''>Select a Make</option>
              {{/ this.makeId }}
              {{# for( make of this.makes.value) }}
                <option value:from="make.id">{{ make.name }}</option>
              {{/ for }}
            {{/ if }}
        </select>

        {{# if(this.modelsPromise) }}
            {{# if(this.models) }}
                <select value:bind="this.modelId">
                    {{^ this.modelId }}
                        <option value=''>Select a Model</option>
                    {{/ this.modelId }}
                    {{# for(model of this.models) }}
                        <option value:from="model.id">{{ model.name }}</option>
                    {{/ for }}
                </select>
            {{ else }}
                <select disabled><option>Loading Models</option></select>
            {{/ if }}
        {{ else }}
            <select disabled><option>Models</option></select>
        {{/ if }}

        {{# if(this.years) }}
            <select value:bind="this.year">
                {{^ this.year }}
                    <option value=''>Select a Year</option>
                {{/ this.year }}
                {{# for(year of this.years ) }}
                    <option value:from="year">{{ year }}</option>
                {{/ for }}
            </select>
        {{ else }}
            <select disabled><option>Years</option></select>
        {{/ if }}

        <div>
            {{# for(vehicle of this.vehicles) }}
                <h2>{{ vehicle.name }}</h2>
                <img src:from="vehicle.thumb" width="200px"/>
            {{/ for }}
        </div>
    `;

    static props = {
        makeId: type.maybeConvert(String),
        makes: {
            get() {
                return ajax({
                    type: "GET",
                    url: "/makes"
                }).then(resp => resp.data);
            }
        },
        modelId: {
            type: String,
            value({ lastSet, listenTo, resolve }) {
                listenTo(lastSet, resolve);

                listenTo("makeId", () => resolve(""));
            }
        },
        get modelsPromise() {
            let makeId = this.makeId;
            if( makeId ) {
                return ajax({
                    type: "GET",
                    url: "/models",
                    data: { filter: { makeId } }
                }).then(resp => {
                    return resp.data;
                });
            }
        },
        models: {
            async(resolve) {
                let promise = this.modelsPromise;
                if(promise) {
                    promise.then(resolve);
                }
            }
        },
        get model() {
            let models = this.models,
                modelId = this.modelId;

            if(models && models.length && modelId) {
                let matched = models.filter(model => {
                    return modelId == model.id;
                });
                return matched[0];
            }
        },
        get years() {
            let model = this.model;
            return model && model.years;
        },
        year: {
            type: String,
            value({ lastSet, listenTo, resolve }) {
                listenTo(lastSet, resolve);

                listenTo("modelId", () => resolve(""));
            }
        },
        vehicles: {
            async(resolve) {
                let year = this.year,
                    modelId = this.modelId;

                if(modelId && year) {
                    ajax({
                        type: "GET",
                        url: "/vehicles",
                        data: { filter: { modelId, year } }
                    }).then(resp => {
                        resolve(resp.data);
                    });
                } else {
                    resolve([]);
                }
            }
        }
    };
};
customElements.define("my-mmy", MyMmy);
</script>