使用 Web API 和 AngularJS 保存表单数据(选择列表)

Posted

技术标签:

【中文标题】使用 Web API 和 AngularJS 保存表单数据(选择列表)【英文标题】:Saving Form Data using Web API and AngularJS (select list) 【发布时间】:2017-07-01 02:53:04 【问题描述】:

我有一个显示人员数据并提供更新人员信息并将更改保存到我的数据库的功能的表单。见下表:

绑定到文本框的字段我更新没有问题。但是,当涉及到 html 选择列表(下拉列表)时,我无法保存新选择的值。

注意我可以在任意数量的文本框中进行更改,然后更改选择列表中的选择,然后表单的其余部分会正确保存,而无需更改选择列表,所以它似乎没有在任何地方失败。

我没有收到任何错误;但是,我在 PUT 之前看到了一个额外的 OPTIONS 请求,我不确定(因此,任何其他关于为什么会这样的提示也将不胜感激)。

这是我的表格:

<form name="personForm" novalidate ng-controller="PersonnelEditCtrl as vm">
<fieldset class="col-md-4">
    <legend>Basic Personnel Information</legend>
    <div class="form-group row" ng-class="'has-error':personForm.inputLastName.$invalid && personForm.inputLastName.$dirty">
        <label class="col-md-3 control-label" for="inputLastName">Last Name</label>
        <div class="col-md-4">
            <input class="form-control" id="inputLastName" name="inputLastName" 
                   type="text" placeholder="Last Name (required)" 
                   ng-model="vm.person.lastName" required ng-minlength="1" ng-maxlength="30" />
        </div>
        <span class="help-block" has-error">
            <span ng-show="personForm.inputLastName.$error.required">
                Last name is required.
            </span>
            <span ng-show="person.form.inputLastName.$error.minlength">
                Last name must be at least 1 character in length.
            </span>
            <span ng-show="person.form.inputLastName.$error.maxlength">
                Last name cannot exceed 30 characters in length.
            </span>
        </span>
    </div>
    <div class="form-group row" ng-class="'has-error':personForm.inputFirstName.$invalid && personForm.inputFirstName.$dirty">
        <label class="col-md-3 control-label" for="inputFirstName">First Name</label>
        <div class="col-md-4">
            <input class="form-control" id="inputFirstName" name="inputFirstName" 
                   type="text" placeholder="First Name (required)" 
                   ng-model="vm.person.firstName" required ng-minlength="1" ng-maxlength="30" />
        </div>
        <span class="help-block" has-error">
            <span ng-show="personForm.inputFirstName.$error.required">
                First name is required.
            </span>
            <span ng-show="person.form.inputFirstName.$error.minlength">
                First name must be at least 1 character in length.
            </span>
            <span ng-show="person.form.inputFirstName.$error.maxlength">
                First name cannot exceed 30 characters in length.
            </span>
        </span>
    </div>
    <div class="form-group row" ng-class="'has-error':personForm.inputMiddleInitial.$invalid && personForm.inputMiddleInitial.$dirty">
        <label class="col-md-3 control-label" for="inputMiddleInitial">Middle Initial</label>
        <div class="col-md-4">
            <input class="form-control" id="inputMiddleInitial" name="inputMiddleInitial" 
                   type="text" placeholder="Middle Initial (required)" 
                   ng-model="vm.person.middleInitial" required ng-minlength="1" ng-maxlength="1" />
        </div>
        <span class="help-block" has-error">
            <span ng-show="personForm.inputMiddleInitial.$error.required">
                Middle initial is required.
            </span>
            <span ng-show="person.form.inputMiddleInitial.$error.minlength">
                Middle initial must be at least 1 character in length.
            </span>
            <span ng-show="person.form.inputMiddleInitial.$error.maxlength">
                Middle initial cannot exceed 1 characters in length.
            </span>
        </span>
    </div>
    <div class="form-group row">
        <label class="col-md-3 control-label" for="inputDateOfBirth">Date of Birth</label>
        <div class="col-md-4">
            <input class="form-control" ng-model="vm.person.dob" type="date" />
        </div>
    </div>
    <div class="form-group row">
        <label class="col-md-3 control-label" for="selectPayband">Payband</label>
        <div class="col-md-4">

            <select id="selectPayband" name="selectPayband" 
                    ng-model="vm.person.payband" ng-options="payband.name for payband in vm.paybands track by payband.id">
            </select>
        </div>
    </div>
    <div class="form-group row">
        <div class="col-md-4">
            <span>
                <button class="btn btn-primary" style="width:80px; margin-right:10px" 
                        ng-click="vm.submit()" ng-disabled="personForm.$invalid">Save</button>
            </span>
            <span>
                <button class="btn btn-default" style="width:70px" 
                        ng-click="vm.cancel(personForm)">Cancel</button>
            </span>
        </div>
    </div>
    <div class="form-group row" ng-show="vm.message">
        <div class="col-md-6">
            <pre style="font: inherit"> vm.message </pre>
        </div>
    </div>
</fieldset>

personnelEditCtrl.js

angular
.module("personnelService")
.controller("PersonnelEditCtrl",
             PersonnelEditCtrl);

function PersonnelEditCtrl(personnelResource, paybandResource, $filter) 
var vm = this;
vm.person = ;
vm.message = '';
vm.paybands = [];

paybandResource.query(function (data) 
    vm.paybands = $filter('orderBy')(data, 'Name');
);

personnelResource.get( id: 2 ,
    function (data) 
        vm.person = data;
        vm.person.dob = new Date(vm.person.dob);
        vm.originalPerson = angular.copy(data);
    );

if (vm.person && vm.person.personId) 
    vm.title = "Edit: " + vm.person.firstName + " " + vm.person.lastName;

else 
    vm.title = "New Person";


vm.submit = function () 
    vm.message = '';
    if (vm.person.personId) 
        vm.person.$update( id: vm.person.personId ,
            function (data) 
                vm.message = '... Save Complete';
            )
    
    else 
        vm.person.$save(
            function (data) 
                vm.originalPerson = angular.copy(data);
                vm.message = '... Save Complete';
            )
    
;

vm.cancel = function (editForm) 
    editForm.$setPristine();
    vm.person = angular.copy(vm.originalPerson);
    vm.message = "";
;

personnelResource.js

(function () 
"use strict";

angular
    .module("common.services")
    .factory("personnelResource",
            ["$resource",
             "appSettings",
                personnelResource])

function personnelResource($resource, appSettings) 
    return $resource(appSettings.serverPath + "/api/people/:id", null,
        
            'update':method:'PUT'
        );

());

paybandResource.js

(function () 
"use strict";

angular
    .module("common.services")
    .factory("paybandResource",
            ["$resource",
             "appSettings",
                paybandResource])

function paybandResource($resource, appSettings) 
    return $resource(appSettings.serverPath + "/api/paybands/:id");

());

数据库结构:

dbo.People

PersonId : int (PK)
FirstName : string
MiddleInitial: string
LastName : string
DateOfBirth: datetime
PaybandId : int (FK)

dbo.Paybands

Id : int (PK)
Name : string

这可能与它无关,但我也会为“People”发布我的 Web API 控制器代码:

using System.Linq;
using System.Web.Http;
using CPS.WebAPI.Models;
using System.Web.Http.Cors;
using System.Data.Entity;

namespace CPS.WebAPI.Controllers

[EnableCorsAttribute("http://localhost:53265", "*", "*")]
public class PeopleController : ApiController

    private CPS_Context db = new CPS_Context();

    public IQueryable<Person> GetPeople()
    
        return db.Person;
    

    public Person Get(int id)
    
        Person person;

        if (id > 0)
        
            var people = db.Person;
            person = people.FirstOrDefault(p => p.PersonId == id);
        
        else
        
            person = db.Person.Create();
        

        return person;
    

    public void Post([FromBody]Person person)
    
        CPS_Context db = new CPS_Context();
        var newPerson = db.Person.Add(person);
        db.SaveChanges();
    

    public void Put(int id, [FromBody]Person person)
    
        CPS_Context db = new CPS_Context();
        db.Entry(person).State = EntityState.Modified;
        var updatedPerson = db.SaveChanges();
    

    public void Delete(int id)
    

    


不要介意 Web API 的最低限度代码,我只是从头开始做所有事情,并尽可能少地做所有事情以使其同时工作。

非常感谢您提供的任何帮助,帮助我将所选选项保存在我的选择列表中。如果您有任何进一步的问题或需要更多信息,请告诉我 - 我尽量做到彻底。再次提前感谢任何人都可以提供的任何帮助!

【问题讨论】:

您是否尝试过 ng-change 对传递 ng-model 的 select 并查看它是否在那里发生了变化? 我还没有 - 我仍然掌握 Angular 的窍门。我现在将研究该指令。谢谢 所以,是的,我让 ng-update 工作(只是将选定的值推送到一个数组并显示它)。所以我不确定为什么它不想将新选择的值保存在选择列表中,但如果它在文本框中,它会保存其他所有内容。 不保存选择值是什么意思?选择值是否真的被设置了?你为什么在选择中这样做 vm.person.payband = payband.id 看起来person.payband 应该是payband id,所以选择ngOptions 不应该是ng-options="payband.id as payband.name for payband in vm.paybands"。此外,尝试将 vm.person.payband 放在模板中的某个位置,更改选择并检查值是否符合您的预期。 【参考方案1】:

我的问题原来是 JSON 数据包含导航属性。更新失败,因为存在参照完整性冲突。

我的问题的解决方案是更新我的实体框架数据模型以从 JSON 中排除导航属性。我通过添加这样的 [JsonIgnore] 属性来做到这一点:

[ForeignKey("Payband")]
public virtual int PaybandId  get; set; 

[JsonIgnore]
public virtual Payband Payband  get; set; 

【讨论】:

以上是关于使用 Web API 和 AngularJS 保存表单数据(选择列表)的主要内容,如果未能解决你的问题,请参考以下文章

使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组

在 AngularJS 中使用 POST 到 .net Web API 时出错

Web API 和 AngularJs

AngularJS客户端路由和令牌认证与web api

WEB API AngularJS Google+Login CORS 不允许

使用AngularJS查询Web API