我正在寻找解决验证问题的选项/最佳做法。
我有一个使用angular.js的Asp.net MVC4应用程序。我的angular viewmodel有一个名为Vendor的对象。供应商有一系列名为“联系人”的联系人。
我想允许用户在提交表单之前输入多个联系人,但我也希望对每个联系人进行验证。在将联系人添加到“联系人”阵列之前,用户需要添加“姓名”,“电话”,“传真...”等。但是,当他们提交整个表单时,我不希望子表单字段使表单无效。
我已经研究过嵌套表单,但似乎没有一种方法可以使用单独的表单和子表单作用域进行验证。在我的例子中,主窗体和子窗体字段需要完全分开。 (即在添加联系人时验证子表单,在提交主表单时验证主表单)
我目前的解决方案是在ContactController addContact方法上添加自定义验证例程。
这是我的代码......
index.cshtml
<form role="form" name="Ctrl.vendorForm" data-ng-submit="vendorForm.$valid && Ctrl.updateVendor" id="vendor" class="form-horizontal" data-ng-controller="VendorController as Ctrl" novalidate>
...
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href="#ContactsPanel" data-toggle="collapse" data-parent="#accordian">Contact Persons</a>
</h4>
</div>
<div class="panel-collapse collapse in" id="ContactsPanel">
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<div class="pull-left" data-ng-repeat="contact in Ctrl.Vendor.Contacts">
<!-- use custom directives as Attributes (not Elements) to be IE8 friendly (IE9 issue??) -->
<div data-contact-card data-contact="contact" data-delete-contact="Ctrl.deleteContact(parmContact)"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 pull-left">
<!-- UI Bootstrap -->
<!-- <button class="btn btn-primary" data-ng-click="Ctrl.shoMo()">Show me the Modal</button>-->
<div id="contactForm" data-ng-controller="ContactController as contactCtrl">
<h4>Create New Contact</h4>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.FirstName" class="form-control" type="text" required placeholder="Enter first name..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.Last_Name" class="form-control" type="text" placeholder="Enter last name..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.ContactEmail" class="form-control" type="email" placeholder="Enter email address..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.Telephone" class="form-control" type="text" placeholder="Enter phone number..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.ContactPhoneExtension" class="form-control" type="text" placeholder="Enter phone extension..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.ContactFax" class="form-control" type="text" placeholder="Enter fax number..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.ContactFaxExtension" class="form-control" type="text" placeholder="Enter fax extension..." />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input data-ng-model="contactCtrl.contact.PrimaryContact" type="checkbox" /> Primary Contact<br/>
<input data-ng-model="contactCtrl.contact.AcctReceivableContact" type="checkbox" /> Accounts Receivable Contact<br />
<input data-ng-model="contactCtrl.contact.PurchaseOrderContact" type="checkbox" /> Purchase Order Contact<br />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input type="submit" data-ng-click="contactCtrl.addContact(Ctrl.Vendor)" class="btn btn-primary btn-xs pull-right" value="Save Contact" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Submit Form
</h4>
</div>
<div id="SubmitPanel">
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-xs">View Code of Conduct</button>
</div>
<div class="col-sm-12">
<input name="CodeOfConductAccepted" data-ng-model="Ctrl.Vendor.CodeOfConductAccepted" type="checkbox" required /> I have read and agree to accept the Code of Conduct.
<p data-ng-show="vendorForm.CodeOfConductAccepted.$invalid" class="validation-message">You must accept the Code of Conduct before you can submit the form.</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input type="submit" class="btn btn-default btn-lg" data-ng-disabled="vendorForm.$invalid" value="Submit">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
app.js
(function () {
var app = angular.module("vendorApp", [])
app.controller('ContactController', function () {
this.contact = {};
this.counter = 0;
this.addContact = function (Vendor) {
if (_.isEmpty(this.contact.FirstName)) {
alert("First Name is required");
return;
}
if (_.isEmpty(this.contact.Last_Name)) {
alert("Last Name is required");
return;
}
if (_.isEmpty(this.contact.ContactEmail)) {
alert("Email Address is required");
return;
}
if (_.isEmpty(this.contact.Telephone)) {
alert("Telephone is required");
return;
}
if (this.contact.PrimaryContact || this.contact.AcctReceivableContact || this.contact.PurchaseOrderContact) {
this.counter = this.counter + 1;
this.contact.IsNew = true;
this.contact.ClientID = this.counter;
Vendor.Contacts.push(this.contact);
this.contact = {};
}
else
{
alert("You must select a contact type.");
}
});
app.directive('contactCard', function () {
return {
restrict: 'AE',
templateUrl: '/Template/ContactCard',
scope: {
contact: '=',
deleteContact: '&'
}
};
});
}());
vendorCtrl.js
(function () {
var vendorController = function (vendorService, $location, $modal) {
var _this = this;
this.getVendor = function (id) {
vendorService.getVendor(id).success(function (data) {
angular.extend(_this, data);
})
};
this.deleteContact = function (contact) {
if (contact.IsNew) {
_.remove(_this.Vendor.Contacts, contact);
}
else {
alert("Perform Server Side Delete");
}
};
};
vendorController.$inject = ['VendorService', '$location', '$modal'];
angular.module("vendorApp")
.controller('VendorController', vendorController);
}());
_ContactCard.cshtml
<div class="well">
<input type="button" data-ng-click="deleteContact({parmContact: contact})" class="btn btn-primary btn-xs pull-right" value="X" />
<strong>{{contact.FirstName}} {{contact.Last_Name}}</strong><br />
<small>
<i>
<strong>
<span data-ng-show="contact.PrimaryContact">Primary Contact<br /></span>
<span data-ng-show="contact.AcctReceivableContact">Accounts Receivable Contact<br /></span>
<span data-ng-show="contact.PurchaseOrderContact">Purchase Order Contact<br /></span>
</strong>
</i>
Email: {{contact.ContactEmail}}<br />
Phone: {{contact.Telephone}} <span data-ng-show="contact.ContactPhoneExtension.length">x{{contact.ContactPhoneExtension}}</span><br />
Fax: {{contact.ContactFax}} <span data-ng-show="contact.ContactFaxExtension.length">x{{contact.ContactFaxExtension}}</span><br />
</small>
</div>
谢谢, 约翰