我遇到多步问题并在输入时提交。我已经按照this教程创建了一个多步骤表单。
现在的问题是当你在第一步中按Enter键提交表单时,这不是意图。
我有一个像这样的通用form.html:
<form id="appointment-form" name="appointmentform" ng-submit="processForm(appointmentform.$valid)">
<!-- our nested state views will be injected here -->
<div id="form-views" ui-view></div>
</form>
我也有
form-license.html(第1步)
<!-- form-license.html -->
<label>Nummerplaat ingeven</label>
<div class="form-group">
<div class="col-xs-8 col-xs-offset-2">
<input required type="text" class="form-control" name="license" ng-model="formData.license">
</div>
</div>
<div class="form-group row">
<div class="col-xs-4 col-xs-offset-4">
<a ng-click="next(1)" ng-disabled="!licenseValidated" class="btn btn-next btn-block">
Volgende
</a>
</div>
</div>
form-profile.html(第2步)
<div class="profile">
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="name" ng-model="formData.profile.name">
</div>
</div>
<div class="form-group row">
<div class="col-xs-8 col-xs-offset-2">
<a ng-click="next(1)" ui-sref="form.license" class="btn btn-block btn-previous col-xs-3">
VORIGE
</a>
<a ng-click="next(2)" ng-disabled="!infoValidated" class="btn btn-block btn-next col-xs-3">
Volgende
</a>
</div>
</div>
</div>
form-appointment.html(第3步)
<div class="appointment">
<!-- form-payment.html -->
<div class="text-center">
<div id="calendar" class="span8 calendar" ui-calendar="uiConfig.calendar" full-calendar ng-model="eventSources"></div>
<div id="appointment_hours">
<div ng-repeat="(key, value) in formData.appointments">
<input id='<% key %>' type='radio' ng-model='formData.appointment_hour' ng-change="change('<% key %>')" name='appointment' value='<% key %>'>
<!-- change int to string -->
<label for='<% key %>'><% key | format_time %></label><br>
</div>
</div>
<div class="form-group row">
<div class="col-xs-8 col-xs-offset-2">
<a ng-click="next(2)" ui-sref="form.profile" class="btn btn-block btn-previous col-xs-3">
VORIGE
</a>
<button type="button" class="btn btn-block btn-next col-xs-3">VOLGENDE</button>
</div>
</div>
</div>
</div>
我的配置和控制器如下所示:
// app.js
// create our angular app and inject ngAnimate and ui-router
// =============================================================================
angular.module('formApp', ['ngAnimate', 'ui.router', 'ui.calendar'])
// configuring our routes
// =============================================================================
.config(function($stateProvider, $urlRouterProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
$stateProvider
// route to show our basic form (/form)
.state('form', {
url: '/form',
templateUrl: 'views/form.html',
controller: 'formController'
})
// nested states
// each of these sections will have their own view
// url will be /form/interests
.state('form.license', {
url: '/license',
templateUrl: 'views/form-license.html'
})
// url will be nested (/form/profile)
.state('form.profile', {
url: '/profile',
templateUrl: 'views/form-profile.html'
})
// url will be /form/payment
.state('form.appointment', {
url: '/appointment',
templateUrl: 'views/form-appointment.html'
})
// url will be /form/success
.state('form.success', {
url: '/success',
templateUrl: 'views/form-success.html'
});
// catch all route
// send users to the form page
$urlRouterProvider.otherwise('/form/license');
})
// our controller for the form
// =============================================================================
.controller('formController', function($scope, $http, $compile, $state, uiCalendarConfig) {
console.log($scope.agendaValidated);
$scope.change = function(key){
// get number of available spots
var n_appointments = $scope.formData.appointments[key];
var first_available = n_appointments[0];
// set column id
$scope.formData.column_id = first_available.column_id;
};
$scope.obj = {
licenseplate: true
};
$scope.calendarData = [];
$scope.appointments = [];
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
// we will store all of our form data in this object
$scope.formData = {};
$scope.formData.profile = {};
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
$('.loader').hide();
});
$scope.next = function(step){
$('.loader').show();
if(step == 1) // licensePlate
{
// receive customer data
$http.post('/api/licenseplate', { license: $scope.formData.license })
.success(function(data, status, headers, config){
var item = data.item;
console.log(item);
if(item) // fill in the name, address, email and telephone number
{
$scope.formData.profile.name = item.driver_name;
$scope.formData.profile.street = item.driver_street;
$scope.formData.profile.zipcode = item.driver_zipcode;
$scope.formData.profile.city = item.driver_city;
$scope.formData.profile.email = item.driver_email;
$scope.formData.profile.telephone = item.driver_tel_no;
}
$state.go('form.profile');
})
.error(function(data, status, headers, config) {
console.log("Data: " + data +
"<hr />status: " + status +
"<hr />headers: " + headers +
"<hr />config: " + config);
});
}
else if(step == 2)
{
// save customer data
// get calendar appointments
var current_date = (m+1) + '/' + d + '/' + y;
$http.post('/api/calendar', { date: current_date })
.success(function(data, status, headers, config){
console.log(data);
var item = data.items.item;
item.sort(function(a, b) {
return a.column_id - b.column_id;
});
$scope.calendarData.pop();
$scope.calendarData.push(item);
$state.go('form.appointment');
})
.error(function(data, status, headers, config) {
console.log("Data: " + data +
"<hr />status: " + status +
"<hr />headers: " + headers +
"<hr />config: " + config);
});
}
};
// function to process the form
$scope.processForm = function(isValid) {
$('.loader').show();
var appointment_date = $scope.formData.appointment_date;
var appointment_hour = $scope.formData.appointment_hour;
var column_id = $scope.formData.column_id;
var profile = $scope.formData.profile;
var license = $scope.formData.license;
$http.post('/api/agendainsert', { appointment_datetime: appointment_date + appointment_hour, profile: profile, column_id: column_id, license: license })
.success(function(data, status, headers, config){
$state.go('form.success');
})
.error(function(data, status, headers, config) {
console.log("Data: " + data +
"<hr />status: " + status +
"<hr />headers: " + headers +
"<hr />config: " + config);
});
};
///////////////////////////
// validation functions //
/////////////////////////
$scope.error = {};
// STEP 1
$scope.$watch('formData.license', function (newVal) {
$scope.licenseValidated = validateLicense(newVal);
});
var validateLicense = function (newVal) {
// check if valid license
/*$http.post('/api/licensevalidate', { license: newVal })
.success(function(data, status, headers, config){
if(data == 1)
{
$scope.licenseValidated = true;
}
})
.error(function(data, status, headers, config) {
console.log("Data: " + data +
"<hr />status: " + status +
"<hr />headers: " + headers +
"<hr />config: " + config);
});*/
// If you are only checking for content to be entered
return (newVal !== '' && newVal !== undefined);
};
// STEP 2
$scope.$watchGroup(['formData.profile.name', 'formData.profile.street', 'formData.profile.zipcode', 'formData.profile.city', 'formData.profile.email', 'formData.profile.telephone'], function (newVal) {
$scope.infoValidated = validateInfo(newVal);
});
var validateInfo = function (newVal) {
if (newVal.length > 0) {
for (var i = 0, l = newVal.length; i < l; i++) {
if (newVal[i] === undefined || newVal[i] === '') {
return false;
}
}
return true;
}
return false;
};
});
问题是,当您在第一步或第二步中输入时,它提交表单并且数据未正确发布。它调用函数processForm。但我只想在最后一步调用函数processForm。
如何让这项工作在你点击进入第一步时进入第二步?我已经尝试禁用enter按钮,但它不能用于指令。
答案 0 :(得分:3)
您需要创建一个指令来收听表单上的keydown
事件,如果按下的键为enter
keyCode == 13
这是DEMO
包括jquery
创建一个指令disable-enter-submit
并将其附加到表单
<form id="appointment-form" name="appointmentform" ng-submit="processForm()" disable-enter-submit>
实施指令
app.directive('disableEnterSubmit', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
// listen to the keydown event on the form and if the pressed ..
//..key is enter then prevent the default action/s which is submitting the form
element.bind("keydown", function(event) {
if(event.keyCode == 13) {
event.preventDefault();
return false;
}
});
}
}
});
这里有点改进DEMO
--------------------------的更新强> ------------- -------------
如果您在按enter
键
在控制器中创建变量
var total_steps = 2; // total steps of the form
var current_step = 1; // active step
$scope.next = function(step) {
// if current step is equals to total steps then submit the form
if(current_step == total_steps) {
$scope.processForm();
return;
}
// if step is defined then assign the current_step to step
// else increment the current_step by 1
if (!angular.isUndefined(step)) {
current_step = step;
} else {
current_step++;
}
// load the proper template based on step
$scope.form_fields = 'step' + current_step + '.html';
};
指令
element.bind("keydown", function(event) {
if (event.keyCode == 13) {
// if press enter then call the next() function on the scope
// we need to trigger the digest cycle manually
// because `element.bind("keydown"..` happens out of angular knowledge.
// so i wrapped it in a `$timeout` or you can use `scope.$apply();` after the `scope.next();`
$timeout(function() {
scope.next();
});
event.preventDefault();
return false;
}
});
这是DEMO