Angular バリデーションエラー表示
ngModel経由なら、input要素のvalue, error とも取得できる。
<input #foo="ngModel" [(ngModel)]="metas.foo" required> <div>value: {{foo.value}}</div> <div>error: {{foo.errors?.required}}</div>
export class AppComponent { metas = { foo: '', bar: '', baz: '', } }
ngForm経由では、input要素のvalueは取得できても、errorは取得できないっぽい。
(Form全体のエラーは取得できる。)
<form #metaForm="ngForm"> <input name="foo" [(ngModel)]="metas.foo" required> </form> <div>value: {{metaForm.value.foo}}</div> <div>error: {{metaForm.invalid}}</div>
Angular 全て入力後に送信可能になるボタン 2
formを使わないバージョン。応用は効かせやすいかも。
<input [(ngModel)]="metas.foo"><br> <input [(ngModel)]="metas.bar"><br> <input [(ngModel)]="metas.baz"><br> <br> <div>disabled: {{disabled}}</div> <button [disabled]="disabled">Submit</button>
export class AppComponent { metas = { foo: '', bar: '', baz: '', } get disabled() { if (this.metas.foo !== '' && this.metas.bar !== '' && this.metas.baz !== '' ) { return false } return true } }
Angular 全て入力後に送信可能になるボタン 1
Vue.jsに続いて、Angularでも。
テキストフィールドに全て入力完了後、disabledが解除されて送信可能になるボタン。
<form #metaForm="ngForm"> <input name="foo" [(ngModel)]="metas.foo" required><br> <input name="bar" [(ngModel)]="metas.bar" required><br> <input name="baz" [(ngModel)]="metas.baz" required><br> <br> <div>disabled: {{metaForm.invalid}}</div> <button [disabled]="metaForm.invalid">Submit</button> </form>
export class AppComponent { metas = { foo: '', bar: '', baz: '', } }
name属性をつけないと、うまく動かないっぽい。
Angular 複数チェックボックスを全て選択で切り替え
Vue.jsに続いて、Angularで全て選択を切り替え。
<input type="checkbox" [(ngModel)]="metas.foo">foo<br> <input type="checkbox" [(ngModel)]="metas.bar">bar<br> <input type="checkbox" [(ngModel)]="metas.baz">baz<br> <br> <input type="checkbox" [(ngModel)]="all_checked">all<br>
export class AppComponent { metas = { foo: false, bar: false, baz: false, } get all_checked() { return !Object.values(this.metas).includes(false) } set all_checked(checked) { for (const key of Object.keys(this.metas)) { this.metas[key] = checked } } }
Vue.jsの場合、複数チェックボックスの選択値を配列で双方向バインドできるんだけど、Angularはできないのかなぁ…。
AngularのngModelはgetter, setterと相性がいいように感じました。
JavaScript オブジェクトの結合
オブジェクトの結合について、情報整理。
以下、既存のオブジェクトに、別のオブジェクトを結合する場合。
ES6で書けない時はjQueryを使う。
var nogizaka1 = { shiraishi: 'mai', akimoto: 'manatsu', } var nogizaka2 = { hori: 'miona', suzuki: 'ayane', } // jQueryのメソッド $.extend(nogizaka1, nogizaka2) console.log(nogizaka1) // {shiraishi: "mai", akimoto: "manatsu", hori: "miona", suzuki: "ayane"} // ES6 Object.assign(nogizaka1, nogizaka2) console.log(nogizaka1) // {shiraishi: "mai", akimoto: "manatsu", hori: "miona", suzuki: "ayane"}
以下、結合して新しいオブジェクトを生成する場合。
// jQueryのメソッド var nogizaka3 = $.extend({}, nogizaka1, nogizaka2) console.log(nogizaka3) // {shiraishi: "mai", akimoto: "manatsu", hori: "miona", suzuki: "ayane"} // ES6 var nogizaka3 = Object.assign({}, nogizaka1, nogizaka2) console.log(nogizaka3) // {shiraishi: "mai", akimoto: "manatsu", hori: "miona", suzuki: "ayane"} // ES6 スプレッド演算子 var nogizaka3 = { ...nogizaka1, ...nogizaka2 } console.log(nogizaka3) // {shiraishi: "mai", akimoto: "manatsu", hori: "miona", suzuki: "ayane"}
スプレッド演算子を積極的に使いたい。
JavaScript プロパティの初期化
JavaScriptの小ネタ。
以下、よくあるインスタンス生成時のプロパティセット。
var personal_info = { name: 'Tom', age: '20', } function Person(personal_info) { this.name = personal_info.name this.age = personal_info.age this.indroduce_myself = function () { console.log(`私は${this.name}、${this.age}歳です。`) } } var person = new Person(personal_info) person.indroduce_myself() // 私はTom、20歳です。
プロパティセット部分を Object.assign に置き換える。
function Person(personal_info) { Object.assign(this, personal_info) this.indroduce_myself = function () { console.log(`私は${this.name}、${this.age}歳です。`) // 私はTom、20歳です。 } }
だらだらと複数個のプロパティをセットしていく必要が無くなる。
玄人っぽくて良い!
Vue.js Ajaxを使った連動するセレクトボックス
1つ目のセレクトボックスの項目を非同期通信で取得。
そこで選択した項目を元に、2つ目のセレクトボックスの項目も非同期で取得する。
<div id="app"> <select v-model="selected_category_id"> <option v-for="item in category_list" :value="item.id">{{ item.name }}</option> </select> <div>{{ selected_category_id }}</div> <select v-model="selected_animal_id"> <option v-for="item in animal_list" :value="item.id">{{ item.name }}</option> </select> <div>{{ selected_animal_id }}</div> </div>
1つ目のセレクトボックス項目は created 内で取得。
2つ目のセレクトボックス項目は watch 内で取得。
new Vue({ el: '#app', data: { category_list: [], selected_category_id: null, animal_list: [], selected_animal_id: null, }, async created () { this.category_list = (await axios.get('http://localhost/animals/category/')).data this.selected_category_id = this.category_list[0].id }, watch: { async selected_category_id () { this.animal_list = (await axios.get(`http://localhost/animals/animals/${this.selected_category_id}/`)).data this.selected_animal_id = this.animal_list[0].id }, }, })
算出プロパティを使えるかと思ったけど、どうも非同期通信は使えないみたいで…。
そもそも算出プロパティは return で値を返すので、Promise では return を2回返すことはできないという…。