单次注册多字段:逐行提交表单至数据库的AngularJS实现问询
I'll walk you through a full implementation for your requirement—allowing users to add multiple shift rows, then submitting each one individually to your backend API. We'll cover the model, API service, controller, and HTML template, with clean, maintainable code.
1. Data Model (Factory)
First, let's create a reusable factory to define our shift data structure. This keeps model logic centralized and easy to reuse:
angular.module('shiftApp').factory('ShiftModel', function() { function Shift(day, startTime, endTime, breakTime) { this.day = day || ''; this.startTime = startTime || ''; this.endTime = endTime || ''; this.breakTime = breakTime || ''; } // Add validation to ensure all fields are filled before submission Shift.prototype.isValid = function() { return this.day && this.startTime && this.endTime && this.breakTime; }; return Shift; });
2. API Service (Backend Communication)
Next, a dedicated service to handle all API calls. This abstracts HTTP logic from the controller, making it easier to update endpoints or add error handling later:
angular.module('shiftApp').service('ShiftService', function($http) { const API_BASE_URL = '/api/shifts'; // Replace with your actual API endpoint this.createShift = function(shiftData) { return $http.post(API_BASE_URL, shiftData) .then(response => response.data) .catch(error => { console.error('Failed to submit shift:', error); throw error; // Re-throw so the controller can handle user-facing errors }); }; });
3. Controller Logic
The controller manages form state, adds new rows, and handles the row-by-row submission flow. We'll use $q.all() to wait for all submissions to complete:
angular.module('shiftApp').controller('ShiftRegistrationCtrl', function($scope, $q, ShiftModel, ShiftService) { // Initialize with one empty shift row $scope.shifts = [new ShiftModel()]; $scope.isSubmitting = false; $scope.submissionStatus = ''; // Add a new empty shift row to the table $scope.addNewShift = function() { $scope.shifts.push(new ShiftModel()); }; // Remove a shift row (prevent removing the last row) $scope.removeShift = function(index) { if ($scope.shifts.length > 1) { $scope.shifts.splice(index, 1); } }; // Submit all shifts one by one to the API $scope.submitAllShifts = function() { // First validate all rows const invalidShifts = $scope.shifts.filter(shift => !shift.isValid()); if (invalidShifts.length > 0) { $scope.submissionStatus = 'Please fill out all fields for every shift row!'; return; } $scope.isSubmitting = true; $scope.submissionStatus = 'Submitting shifts...'; // Create an array of submission promises const submissionPromises = $scope.shifts.map(shift => ShiftService.createShift(shift)); // Wait for all submissions to finish $q.all(submissionPromises) .then(() => { $scope.submissionStatus = 'All shifts submitted successfully!'; // Reset the form after success $scope.shifts = [new ShiftModel()]; }) .catch(() => { $scope.submissionStatus = 'Some shifts failed to submit. Please try again.'; }) .finally(() => { $scope.isSubmitting = false; }); }; });
4. HTML Template
The view renders the table, input fields, and action buttons, with real-time validation and status feedback:
<div ng-controller="ShiftRegistrationCtrl" class="container mt-4"> <h2>Shift Registration</h2> <!-- Status Message --> <div ng-if="submissionStatus" class="alert mt-3" ng-class="{'alert-success': submissionStatus.includes('success'), 'alert-danger': submissionStatus.includes('failed')}"> {{ submissionStatus }} </div> <!-- Shift Table --> <table class="table table-bordered mt-3"> <thead> <tr> <th>Day</th> <th>Start Time</th> <th>End Time</th> <th>Break Time (mins)</th> <th>Actions</th> </tr> </thead> <tbody> <tr ng-repeat="shift in shifts track by $index"> <td> <select ng-model="shift.day" class="form-control" required> <option value="">Select Day</option> <option value="Monday">Monday</option> <option value="Tuesday">Tuesday</option> <option value="Wednesday">Wednesday</option> <option value="Thursday">Thursday</option> <option value="Friday">Friday</option> </select> </td> <td> <input type="time" ng-model="shift.startTime" class="form-control" required> </td> <td> <input type="time" ng-model="shift.endTime" class="form-control" required> </td> <td> <input type="number" ng-model="shift.breakTime" class="form-control" min="0" required> </td> <td> <button ng-click="removeShift($index)" class="btn btn-sm btn-danger" ng-disabled="shifts.length === 1 || isSubmitting">Remove</button> </td> </tr> </tbody> </table> <!-- Action Buttons --> <button ng-click="addNewShift()" class="btn btn-primary me-2" ng-disabled="isSubmitting">Add New Shift</button> <button ng-click="submitAllShifts()" class="btn btn-success" ng-disabled="isSubmitting || shifts.length === 0">Submit All Shifts</button> </div>
Key Details
- Row-by-Row Submission:
$q.all()ensures we wait for every API call to complete before showing a final status, even if some fail. - Validation: The model's
isValid()method prevents partial submissions. - State Management:
isSubmittingdisables buttons during submission to avoid duplicate requests. - Clean Separation: Separating model, service, and controller keeps code organized and easy to debug.
内容的提问来源于stack exchange,提问作者Gvr

