注意
- angularの問題というより、使い方の問題かも知れないです。
- 検証はしたけど、ソースを追っているわけではないので絶対にコレだ!という解釈でも無いです。
- 明確な回避方法はわからないです。(追記:分かりました。)教えていただければと思います。
事の発端
cakePHPで開発中に、フロントエンドのformをangularでバリデーションしたかった。
比較
きちんと動作するコード
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</head>
<body>
<div ng-controller="sample">
<form name="Form">
<div ng-show="Form.title.$error.required">必須です</div>
<div ng-show="Form.title.$error.maxlength">最大255文字です</div>
<input type="text" name="title" ng-model="title" ng-required="true" ng-maxlength="255">
</form>
</div>
</body>
<script>
var app = angular.module('app', []);
app.controller("sample", function($scope, $http) {
});
</script>
</html>
動作しないコード
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</head>
<body>
<div ng-controller="sample">
<form name="Form">
<div ng-show="Form.data[0][title].$error.required">必須です</div>
<div ng-show="Form.data[0][title].$error.maxlength">最大255文字です</div>
<input type="text" name="data[0][title]" ng-model="data[0][title]" ng-required="true" ng-maxlength="255">
</form>
</div>
</body>
<script>
var app = angular.module('app', []);
app.controller("sample", function($scope, $http) {
});
</script>
</html>
上記コードの差分
inputタグのnameとそれを利用するng-showの値がtitle
かdata[0][title]
かの違い
なぜそんな名前を利用するか?
cakePHPでformの値を受け渡したい場合はdata[hoge]
の様に記述する様にドキュメントに記載されている。
従わなくても問題なく動作するが、値を配列で受渡したかったりすると従っていたほうが無難。
現象
内部的には上手く動作しているのか、firebug等で確認すると、クラスが切り替わっていて条件に合わない場合はng-invalidとか付いている。
しかしバリデーションメッセージの表示(というか、ng-showで利用される、Form.data[0][title].$error.required
への値の受け渡し?)は上手く動作しない。
推測
formタグのnameの次にinputの名前を記述するが、inputの名前が配列の様な形で宣言されることを想定していないのでは無いか?
=> Form.data[0][title]
の data[0][title]
部分
回避方法
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</head>
<body>
<div ng-controller="sample">
<form name="Form" action=".">
<div ng-show="Form['data[0][title]'].$error.required">必須です</div>
<div ng-show="Form['data[0][title]'].$error.maxlength">最大255文字です</div>
<input type="text" name="data[0][title]" ng-model="data[0][title]" ng-required="true" ng-maxlength="255">
</form>
</div>
</body>
<script>
var app = angular.module('app', []);
app.controller("sample", function($scope, $http) {
});
</script>
</html>
ng-showの所をForm['data[0][title]']
という様に変更するのが良いみたいです。
le_panda_noirさんのコメント
これはおそらくForm.data[0][title]がForm["data"][0][title]と評価されてるからだと思われます。つまり、inputでnameがdataの0番目(すでにここでおかしい。普通はここで$errorなどが参照される)のtitle変数(もちろん宣言してないのでundefined)の値が指すプロパティを参照してるという動作だと思われます。Form["data[0][title]"]なら問題なく動作するのではないでしょうか?(実機で調べてないしかなりあやしいので動かなかったらすいません)
と自分の投稿を見てくださった別の方からの参考リンク
をたどった所回避方法が分かりました!
ありがとうございました。