【问题标题】:Angular data binding not working角度数据绑定不起作用
【发布时间】:2015-09-05 20:33:23
【问题描述】:

我一直在努力使用 AngularJs 在 ASP.NET 网络表单中进行数据绑定。

我有以下角度:

 (function () {
        var app = angular.module("registrationModule", []);

        app.factory("exampleService", exampleService);

        function exampleService($http) {
            function getData(id) {
                return $http.post("LegacyPage.aspx/GetData", { id: id })
                .then(function (response) {
                    return response.data; //data comes back as json
                   //Also tried response.data.d
                });
            };

            return {
                getData: getData
            };
        };

        app.controller("MainCtrl", ["$scope", "exampleService", MainCtrl]);

        function MainCtrl($scope, exampleService) {

            $scope.generateText = "Generate";
            $scope.loading = false;


            function onComplete(data) {
                Unload(data);
            }

            function err(reason) {
                Unload("Ajax has failed.");
            }

            $scope.GetData = function (id) {
                Load();
                exampleService.getData(id).then(onComplete, err);
            }

            function Unload(result) {
                $scope.loading = false;
                $scope.generating = false;
                $scope.generateText = "Generate";
                $scope.theData = result; //does not work

                //I have tried (with no success):

                //$scope.$apply(function () {
                //$scope.theData = result;
                //});

                //$scope.theData = JSON.parse(result);

                //$scope.theData = angular.fromJson(result);
            }

            function Load() {
                $scope.loading = true;
                $scope.generating = true;
                $scope.generateText = "Generating...";
            }
        };

    }());

我的 HTML:

<div ng-app="registrationModule">

    <div ng-controller="MainCtrl">
        <input style="display: block; margin: 0 auto;" type="text" class="form-control" placeholder="ID" ng-model="id" />
        <input ng-click="GetData(id)" type="button" class="btn btn-primary btn-lg" value="{{generateText}}" ng-disabled="generating" />

        <div class="row">
            <div class="span10">
                <table class="table table-responsive table-hover table-condensed">
                    <tr>
                        <th>ID</th>
                        <th>Activity Code</th>
                        <th>Duration</th>
                        <th>Date Created</th>
                    </tr>
                    <tr ng-repeat="element in theData">
                        <td>{{element.ID}}</td>
                        <td>{{element.ActivityCode}}</td>
                        <td>{{element.Duration}}</td>
                        <td>{{element.DateCreated}}</td>
                    </tr>
                </table>
                <br />
            </div>
        </div>
    </div>
</div>

代码背后/后端 c#:

[WebMethod]
public static string GetData(int id)
{
    var dt = GetData(id);

    if (dt == null) return "";

    var json = dt.Serialize() ?? "";

    return json;
}

public static string Serialize(this DataTable dt)
{
    if (dt == null)
    {
        throw new NullReferenceException("dt parameter cannot be null");
    }

    try
    {
        var serializer = new JavaScriptSerializer();
        var rows = new List<Dictionary<string, object>>();

        Dictionary<string, object> row;

        foreach (DataRow dr in dt.Rows)
        {
            row = new Dictionary<string, object>();
            foreach (DataColumn col in dt.Columns)
            {
                row.Add(col.ColumnName, dr[col]);
            }
            rows.Add(row);
        }

        return serializer.Serialize(rows);
    }
    catch
    {
        return null;
    }
}

本质上,数据以 JSON 形式返回,但未成功绑定。我将 JSON 恢复为有角度的,但我无法处理它。我想我只是错过了一些非常简单的东西,但还没有找到解决方案

【问题讨论】:

    标签: javascript c# asp.net json angularjs


    【解决方案1】:

    所以想通了。问题是 ng-repeat 无法绑定数据。那是因为数据以字符串的形式返回。所以每个对象的每个属性都是一个字符串,角度显然不喜欢那样。我需要做的就是将后端代码更改为:

     [WebMethod]
    public static List<ReportData> GetData(int id)
    {
        var dt = GetData(id);
    
        if (dt == null) return dt;
    
        var reportElements = dt.ToObjectList<ReportData>();
    
        //var json = dt.Serialize() ?? "";
    
        return reportElements;
    }
    
    public class ReportData
    {
        public int Id { get; set; }
        public string ActivityCode { get; set; }
        public string Duration { get; set; }
        public DateTime DateCreated { get; set; }
    }
    
    public static List<T> ToObjectList<T>(this DataTable table) where T : class, new()
    {
        try
        {
            var list = new List<T>();
    
            foreach (var row in table.AsEnumerable())
            {
                T obj = new T();
    
                foreach (var prop in obj.GetType().GetProperties())
                {
                    try
                    {
                        PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                        propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                    }
                    catch
                    {
                        continue;
                    }
                }
    
                list.Add(obj);
            }
    
            return list;
        }
        catch
        {
            return null;
        }
    }
    

    所以现在它返回了我创建的类的通用列表。我使用扩展方法将我的数据表映射到类。在我的服务中,我现在使用:

         function exampleService($http) {
            function getData(id) {
                return $http.post("LegacyPage.aspx/GetData", { id: id })
                .then(function (response) {
                    return response.data; //data comes back as json
                   //Also tried response.data.d
                });
            };
    
            return {
                getData: getData
            };
        };
    

    在我的卸载函数中:

     $scope.theData = result;
    

    【讨论】:

      【解决方案2】:

      我想我可能发现了你的问题。在您的 getData() 函数中,您将 id 参数命名为“studentId”,但稍后将其称为“id”。这是修复:

      function getData(studentId) {
          return $http.post("LegacyPage.aspx/GetData", {
              id: studentId // This used to be "id", but needed to be "studentId"
          })
          .then(function (response) {
              return response.data;
          });
      };
      

      编辑

      听起来您的问题可能是您的 API 正在返回单个哈希对象,如下所示:

      $scope.theData = {
          ID: 1,
          ActivityCode: 'foo'
          ...etc
      }
      

      如果是这种情况,您不需要使用 ng-repeat 指令来显示一个对象。您只需像这样更改您的视图:

      <div ng-app="registrationModule">
      
          <div ng-controller="MainCtrl">
              <input style="display: block; margin: 0 auto;" type="text" class="form-control" placeholder="ID" ng-model="id" />
              <input ng-click="GetData(id)" type="button" class="btn btn-primary btn-lg" value="{{generateText}}" ng-disabled="generating" />
      
              <div class="row">
                  <div class="span10">
                      <table class="table table-responsive table-hover table-condensed">
                          <tr>
                              <th>ID</th>
                              <th>Activity Code</th>
                              <th>Duration</th>
                              <th>Date Created</th>
                          </tr>
                          <tr>
                              <td>{{theData.ID}}</td>
                              <td>{{theData.ActivityCode}}</td>
                              <td>{{theData.Duration}}</td>
                              <td>{{theData.DateCreated}}</td>
                          </tr>
                      </table>
                      <br />
                  </div>
              </div>
          </div>
      </div>
      

      如果您的 API 返回要迭代的对象数组,您只需要使用 ng-repeat 指令,如下所示:

      $scope.theData = [{
          ID: 1,
          ActivityCode: 'foo'
          ...etc
      }, {
          ID: 2,
          ActivityCode: 'bar'
          ...etc
      }]
      

      【讨论】:

      • 对不起,代码只是一个例子,它实际上是我真实代码中的id。现在的问题在于 ng-repeat
      • @user3574076 不用担心。在范围上设置响应后,你能确认 $scope.theData 是一个数组吗?设置后立即尝试执行 console.log($scope.theData)。
      • 看我的回答,我想通了
      • 太棒了,很高兴你想通了! :)
      【解决方案3】:

      您没有将response.data 绑定到任何变量。您需要在控制器中添加$scope.theData = response.data;

      [编辑:] 更正,被你的代码弄糊涂了。更改您的控制器:

      $scope.theData = result;$scope.theData = result.data;

      至于你的服务,去掉.then(...),因为它什么都不做。

              function getData(studentId) {
                  return $http.post("LegacyPage.aspx/GetData", { id: id });
              };
      

      除非您打算更改响应,在这种情况下您需要添加return

              function getData(studentId) {
                  return $http.post("LegacyPage.aspx/GetData", { id: id })
                  .then(function (response) {
                      return response.data;
                  });
              };
      

      至于标准,我建议使用.catch(err),因为这样您可以链接多个.then(...) 语句并且仍然使用单个错误处理程序。它也更容易阅读。

      exampleService.getData(id).then(onComplete).catch(err);
      

      【讨论】:

      • 是的,很抱歉造成混淆,我也错过了退货声明。我在我的问题中编辑了exampleService。也试过.data.d
      • @user3574076 仍然无法正常工作...?应该在这个时候。尝试在您的服务中填充 ["$http", exampleService]
      • @user3574076 如果这仍然不起作用,请在服务的.then(...) 部分中使用console.log(response);,以查看Google Chrome > 控制台(F12) 中的输出。如果看起来不错,请在 Unload 语句中执行 console.log(result) 以查看那里输出的内容。像这样测试你的链条,看看它在哪里断裂。
      • @ngDeveloper 现在测试一下,结果告诉你
      • @user3574076 也许后端服务器返回了无效的 json,或者它没有将 header mime-type 设置为 application/json,因此 Angular 将其视为字符串。你可以在你的控制器Unload() 中尝试类似console.log(JSON.parse(result)); 的东西。请注意 JSON.parse(...) 仅适用于现代浏览器。
      猜你喜欢
      • 2018-12-25
      • 2014-06-26
      • 2018-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 2015-11-02
      相关资源
      最近更新 更多