2017-01-27 6 views
2

私はインターフェイスがvue.js 2.0に基づいているWebアプリケーションを持っています。vue.jsの別のコンポーネントから1つのコンポーネントをアップデートするには

私はselect2プラグインに基づいて入力を表示するコンポーネントを持っています。

デフォルトでは選択されたオプションが表示されますが、ユーザーがクリックすると、select2が表示され、ユーザーがオプションを変更できるようになります。

コードは次のようになります。

<template> 
<div @click="toggleEdit"> 
    <span v-show="isEnabled"> 
     <select 
      class="form-control" 
      :name="name" 
      :multiple="multiple" 
     > 
      <option v-for="opt in options" :value="opt.id"> {{ opt.text }} </option> 
     </select> 
    </span> 
    <span v-show="!isEnabled"> 
     <div v-if="selectedOptions.length === 0"> 
      {{ emptyText }} 
     </div> 
     <div v-for="opt in selectedOptions"> 
      {{ opt }} 
     </div> 
    </span> 
</div> 
</template> 
<script> 
export default { 
    props: { 
     options: { 
      type: Array, 
      required: false, 
      default: function() { 
       return [] 
      } 
     }, 
     name: { 
      required: true, 
      type: String 
     }, 
     multiple: { 
      required: false, 
      type: Boolean, 
      default: false 
     }, 
     emptyText: { 
      required: false, 
      type: String, 
      default: "" 
     }, 
     sourceUrl: { 
      required: false, 
      type: String, 
      default: "" 
     }, 
     enabled: { 
      required: false, 
      type: Boolean, 
      default: false 
     } 
    }, 

    data() { 
     return { 
      isEnabled: this.enabled 
     } 
    }, 

    watch: { 
     options: { 
      handler: function() { 
       console.log(arguments) 
      }, 
      deep: true 
     } 
    }, 

    mounted: function() { 
     this.select = $(this.$el).find("select"); 
     this.select.select2(); 
     var that = this; 
     this.select.on("change", function(e) { 
      var indexMap = {}; 
      for(var i = 0; i < that.options.length; i++) { 
       that.options[i].selected = false; 
       indexMap[that.options[i].id] = i; 
      } 
      var selected = that.select.select2('val'); 
      if(typeof selected === "string") { 
       selected = [selected]; 
      } 
      for(var i = 0; i < selected.length; i++) { 
       var index = indexMap[selected[i]]; 
       console.log(index) 
       console.log(selected[i]) 
       if(index !== undefined) { 
        var option = that.options[index]; 
        option.selected = true; 
        that.$set(that.options, index, option); 
       } 
      } 
     }) 
     this.select.on("select2:open", function() { 
      that.isEnabled = true; 
     }); 
     this.select.on("select2:close", function() { 
      that.isEnabled = false; 
     }); 
    }, 
    methods: { 
     toggleEdit() { 
      if(this.isEnabled) return; // to pass select2 clicks 
      this.isEnabled = !this.isEnabled; 
      var that = this; 
      this.$nextTick(function() { 
       that.select.select2("open"); 
      }); 
     } 
    }, 
    computed: { 
     selectedOptions: function() { 
      console.log(this.options) 
      return this.options.filter(function(option) { 
       console.log(option.selected); 
       if(option.selected === true) return true; 
       return false; 
      }); 
     } 
    } 
} 

問題がある:私は、このコンポーネントを使用して、複数の異なるselectsを示したいと思います。 Name属性は、model1[field1],model1[field2]、...、model40[field1]、...、model99[field15]のいずれかです。ここで、すべてのモデルNは、それぞれのフィールドを持つデータベースのテーブルに対応しています。

ユーザーがオプションを変更すると、AJAXリクエストは、私が「disableFields」配列を解析し、anotherコンポーネントthisコンポーネントから無効にするこの

{ 
    "errorText": null or "text with error", 
    "disableFields": ["model3[field4]", "model24[field15]"] 
} 

のようなJSONオブジェクトを返す、サーバーに送信する必要があります。これを達成する

一つの方法(擬似コード):

foreach field in disableField: 
    $(document).trigger("disableField" + field); 

そしてthisコンポーネント

var self = this; 
$(document).on("disableField" + this.name, function() { 
    self.isEnabled = false 
}) 

mounted方法で親コンポーネントなしでこれを行うには良い方法はありますか?

+0

将来のために、それを短くしてみてください。あなたの質問は良質だが長すぎる... –

答えて

5

他のコンポーネントと直接通信することはできません。親コンポーネントを使用して、コンポーネント間で通信することができます。some kind of event bus

var bus = Vue() 

コンポーネントAはイベントを送信し、コンポーネントBはイベントをキャッチし、その逆もあります。

// component A 
bus.$emit('cool_event_name', interesting_data) 

// component B 
bus.$on('cool_event_name', function(interesting_data) { 
    console.log(interesting_data) 
}) 
0

あなたの投稿が長すぎてそこにたくさんのものがあるので、達成したいことを実際に得るのは簡単ではありませんが、私は試してみます。何かが欠落している場合は、ただコメントしてください。私はあなたを助けるために編集しようとします。

DISABLED FIELDS

は、私はあなたのdata親のコンポーネント(全体フォーム/ページと、例えばコンポーネント)でこのアレイを有する示唆し、その後:disabledに注意を払ってください<component-instance :disabled='disabled.componentId'>のようなあなたのフィールドにそれを渡します。それはあなたの親データと、この同期一方向を維持しますデータバインディング(それはあなたの親内のすべての変更disabled.componentIdがあなたの子コンポーネントに反映されることを意味します)

解析「無効」JSON

ことがあります返信されたフィールドをdata: { disabled }に割り当てる必要があるので、私の意見ではまっすぐに前進していますが、それがわからない場合は私たちに知らせてください。

コンポーネント間の通信の**他の方法**

あなたは子コンポーネントから親を更新する場合は、Vueのイベントバスやイベントハンドラのいずれかを使用してイベントを使用する必要があります。あなたは子コンポーネントからの特別なデータを渡すために必要とされていない場合<child-component @click='yourParentMethod()'>を使用するかのような子コンポーネントにカスタムイベントemitersを作成することができ、子コンポーネントに :

// child component 
methods: { 
someMethod() => { 
this.emit('customEvent', someData) 
} 
} 

//parent component 
<child-component @customEvent='customEventHandler(dataFromChild)'> 

はそれがお役に立てば幸いです。

3

あなたはグローバル変数なしthis.$rootを使用することができます。

// component A emits an event 
export default { 
    name: 'A', 
    methods: { 
    buttonClicked: function() { 
     this.$root.$emit('myEvent', 'new message!'); 
    } 
    } 

// component B catch your event 
export default { 
    name: 'B', 
    data() { 
    return { 
     message: 'Old message!' 
    } 
    }, 
    mounted: function() { 
    this.$root.$on('myEvent', (text) => { // here you need to use the arrow function 
    this.message = text; 
    }) 
    } 
} 
関連する問題