角度数据绑定无法正常工作

时间:2015-06-19 18:47:29

标签: javascript c# asp.net json angularjs

我一直在使用AngularJs在ASP.NET webforms中进行数据绑定。

我有以下角度:

 (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,但我无法处理它。我想我只是遗漏了一些非常简单的东西,但尚未找到解决方案

3 个答案:

答案 0 :(得分:1)

我想我可能已经找到了你的问题。在你的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
}]

答案 1 :(得分:0)

您没有将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);

答案 2 :(得分:0)

所以想通了。问题是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;