15
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue 0.11-rc2でselectタグのカスケードサンプルを書いてみた

Last updated at Posted at 2014-10-19

Vue 0.11からselectタグとのバインディングがすっきり書けるようになります。この機能を使い、selectタグでよくあるカスケードのサンプルを書いてみました。確認したバージョンはVue 0.11-rc2です。

なお、題材として作成したサンプルはこちらのAnguler版を元にしています。Vueでも同じような感じで書けるようになっていますね。

シンプルなパターン

  • optionタグの表示値とvalue属性が同じ値となっています。
  • options属性に文字列の配列を渡すと自動的にoptionタグを生成してくれます。
  • 子供のselectタグの初期選択値の設定は、$watchを使ってselectedCategoryの変更時に行われるようにしています。
  • デモはこちら

HTML

<div id="main">
  <select v-model="selectedCategory" options="categories">
  </select>
  <select v-model="selectedItem" options="items[selectedCategory]">
  </select>
  {{selectedCategory}} : {{selectedItem}}
</div>

JS

new Vue({
  el: "#main",
  data: {
    selectedCategory: "",
    selectedItem: "",
    categories: ["shapes", "colors", "sizes"],
    items: {
      shapes: ["square", "circle", "ellipse"],
      colors: ["red", "green", "blue"],
      sizes: ["small", "medium", "large"]
    }
  },
  created: function() {
    this.$watch("selectedCategory", function() {
      this.selectedItem = this.items[this.selectedCategory][0];
    });
    this.selectedCategory = "colors";
  }
});

表示値とvalueを変えたパターン

  • 今度はoptionタグの表示値とvalue属性が別になっています。
  • options属性に{text: "Square", value: "square"}のような形式の配列を渡すことで自動的に生成してくれます。
  • デモはこちら

HTML

最初のサンプルと同じため省略。

JS

new Vue({
  el: "#main",
  data: {
    selectedCategory: "colors",
    selectedItem: "red",
    categories: [
      {text: "Shapes", value: "shapes"},
      {text: "Colors",  value: "colors"},
      {text: "Sizes", value: "sizes"}
    ],
    items: {
      shapes: [
        {text: "Square", value: "square"},
        {text: "Circle", value: "circle"},
        {text: "Ellipse", value: "ellipse"}
      ],
      colors: [
        {text: "Red", value: "red"},
        {text: "Green", value: "green"},
        {text: "Blue", value: "blue"}
      ],
      sizes: [
        {text: "Small", value: "small"},
        {text: "Medium", value: "medium"},
        {text: "Large", value: "large"}        
      ]
    }
  },
  created: function() {
    this.$watch("selectedCategory", function() {
      this.selectedItem = this.items[this.selectedCategory][0].value;
    });
    this.selectedCategory = "colors";
  }
});

computedを使ったパターン

  • 上記のサンプルは直接バインディング可能なデータ形式で保持していましたが、異なる形式で保持している場合はcomputedを使って動的に変換して対応することもできます。
  • これまではcategoriesとitemsが別の配列でしたが、1つの構造化データになっています。
  • デモはこちら

HTML

<div id="main">
  <select v-model="selectedCategory" options="categories">
  </select>
  <select v-model="selectedItem" options="items">
  </select>
  {{selectedCategory}} : {{selectedItem}}
</div>

JS

// dummy response data
var response = [{
    text: "Shapes",
    value: "shapes",
    items: [
      {
        text: "Square",
        value: "square"},
      {
        text: "Circle",
        value: "circle"
      },
      {
        text: "Ellipse",
        value: "ellipse"
      }
    ]
  },
  {
    text: "Colors",
    value: "colors",
    items: [
      {
        text: "Red",
        value: "red"
      },
      {
        text: "Green",
        value: "green"
      },
      {
        text: "Blue",
        value: "blue"
      }
    ]    
  },
  {
    text: "Sizes",
    value: "sizes",
    items: [
      {
        text: "Small",
        value: "small"
      },
      {
        text: "Medium",
        value: "medium"
      },
      {
        text: "Large",
        value: "large"
      }
    ]    
  }
];

new Vue({
  el: "#main",
  data: {
    selectedCategory: "",
    selectedItem: "",
    response: null
  },
  created: function() {
    var self = this;
    
    // dummy ajax
    setTimeout(function() {
      self.response = response;
      self.selectedCategory = "colors";
    }, 100);
  },
  computed: {
    categories : function() {
      return _.map(this.response, function(val) {
        return {text: val.text, value: val.value};
      });
    },
    items: function() {
      console.log("items");
      var self = this;
      var category = _.find(this.response, function(val) {
          return val.value === self.selectedCategory;
      });
      var items = _.map(category.items, function(val) {
        return {text: val.text, value: val.value};
      });
      this.selectedItem = items[0].value;
      return items;
    }
  }
});
15
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?