如何为发票表单创建嵌套控制器和数组?

时间:2013-10-05 19:43:46

标签: angularjs

由于发票行计算的复杂性,我需要创建发票行作为独立控制人的发票。
我的问题是: 如何定义InvoiceLine控制器数组并使用ng-repeat绑定它们?

我是Angular的新手,在淘汰赛中我做到了这样:http://knockoutjs.com/examples/cartEditor.html

    <script type="text/javascript">
    var invoiceTest = angular.module("InvoiceTest", []);

    invoiceTest.controller(
        "InvoiceHead",
        function ($scope) {
            // how to define ? $scope.InvoiceLine = [array of controllers]
            $scope.VAT = 0.17;
            $scope.TotalNoVat = ???; // Neet To Calc the Sum of $scope.InvoiceLine.TotalCost
            $scope.TotalInvluceVAT = function() {
                return ($scope.TotalNoVat * (1+ $scope.VAT)).toFixed(2);
            };
        }
        );

    invoiceTest.controller("InvoiceLine",
        function ($scope) {
            $scope.Description = "";
            $scope.Quantity = 1;
            $scope.Cost = 0;
            $scope.TotalCost = function() {
                return ($scope.Quantity * $scope.Cost).toFixed(2);
            };

            //more complex  calculation and ajax ...
        }
    );

</script>

1 个答案:

答案 0 :(得分:2)

如果发票行项目有一个UI组件(我想它会这样做),这听起来像是一个使用AngularJS Directive

的好地方

该指令将包含显示发票行项目所必需的逻辑,它可以包含(通过其控制器)计算值以显示行项目所需的逻辑。

如果您希望更多地分离您的问题,您还可以创建一个AngularJS Service来保存计算订单项值的逻辑,inject the service into your directive's controller.这样做的好处是允许您可以对计算逻辑进行单元测试,而无需涉及显示逻辑。

以上是上述使用的服务和指令的真实基本示例(使用MainInvoiceController来保存lineItems):

invoiceTest.controller("MainInvoiceController", function($scope){

    // lineItem directive will update Quantity & Cost as user changes
    // changes input values, and recalculate TotalCost any time either
    // Quantity or Cost changes.
    $scope.lineItems = [
        {
            Description : "Item 1",
            Quantity: 2,
            Cost: 2.00,
            TotalCost: 4.00
        },
        {
            Description : "Item 2",
            Quantity: 10,
            Cost: 4.00,
            TotalCost: 40.00
        },
    ]
});

invoiceTest.service("InvoiceCalculationsService", function(){
    // Calculates the total cost of the line item, and
    // updates the TotalCost property of the line item
    this.updateTotalCost = function(lineItemData)
    {
        lineItemData.TotalCost = lineItemData.Quantity * lineItemData.Cost;
    }
});

InvoiceTest.directive("lineItemDisplay", function(InvoiceCalculationsService){
    return {
        restrict:"AE",
        scope:{
            // lineItemData is expected to contain the properties:
            // Description
            // Quantity
            // Cost
            // TotalCost
            lineItem:"="
        },
        controller: function($scope, $element, $attrs){
            this.recalculateTotal = function(){
                InvoiceCalculationsService.updateTotalCost($scope.lineItem);
            }
        },
        template:   'Description: <input data-ng-model="lineItem.Description" />'
                    'Quantity: <input data-ng-model="lineItem.Quantity" data-ng-change="recalculateTotal()" />' +
                    'Cost: <input data-ng-model="lineItem.Cost" data-ng-change="recalculateTotal()" />' + 
                    'Total: <span>{{lineItem.TotalCost}}</span>'
    }
});

这是使用中的指令,使用`ng-repeat':

<div data-ng-controller="MainInvoiceController">
<ul>
    <li data-ng-repeat="lineItem in lineItems">
        <line-item-display data-line-item="lineItem"></line-item-display>
    </li>
</ul>
</div>