AngularJs,减少html模板中的逻辑

时间:2014-11-30 19:43:10

标签: javascript json angularjs asp.net-web-api

我有一个html模板,其中ng-ifs和ng-shows中的条件变得有点过于复杂而无法归属于UI。例如,这是为了确定是否应显示付款控件:

<div ng-show="ticket.status == 0 && 
  ((ticket.orgTicketId === '' && ticketControl.balance > 0 ) || 
  (ticket.orgTicketId !== '' && ticketControl.balance < 0))">

我想将此简化为:

<div ng-show="ticket.paymentsAllowed">

我宁愿不将逻辑移到控制器中,因为我试图尽可能保持它的清洁。

在C#中,我来自哪里,我只想在Tickets类中添加一个名为PaymentsAllowed的属性,并在那里移动逻辑。

我对Javascript和AngularJs相当陌生,我正在寻找有关如何在此处完成类似工作的建议,以便我可以清理html模板并使其更清晰。

Angular应用程序从WebAPI后端获取JSON,我只是将其分配给$ scope;这一切都运作良好。以下是检索故障单的简化示例。

ticketService从后端读取故障单视图模型:

function getTicket(ticketId) {
    var deferred = common.$q.defer();

    common.$http.get("api/tickets/" + ticketId)
      .success(function (ticket) {
         deferred.resolve(ticket);
      }));

    return deferred.promise;
}

控制器使用ticketService检索票证并分配给$ scope.ticket:

ticketService.getTicket(123).then(
  function (ticket) {
    $scope.ticket = ticket;
  });

我喜欢从WebAPI以JSON数据的形式检索视图模型并将其直接绑定到适当的范围的简单性,但是为这些javascript添加一些简单的业务逻辑的简单,干净的方法是什么对象吗

6 个答案:

答案 0 :(得分:2)

我喜欢&#34;复活&#34;数据作为json重新执行,其行为可以补充数据,例如:

function Ticket(data) {
  angular.copy(data, this); // copy json data into this, which will have our prototype.
}  
Ticket.prototype.paymentsAllowed = function (ticketControl) {
  return this.status == 0 && 
    ((this.orgTicketId === '' && ticketControl.balance > 0 ) || 
    (this.orgTicketId !== '' && ticketControl.balance < 0))
}

function getTicket(ticketId) {
  var deferred = common.$q.defer();

  common.$http.get("api/tickets/" + ticketId)
    .success(function (ticket) {
       deferred.resolve(new Ticket(ticket));
    }));

  return deferred.promise;
}

范围内的故障单将通过原型继承具有方法paymentsAllowed(..),可以在模板中访问,如此

<div ng-show="ticket.paymentsAllowed(ticketControl)">

答案 1 :(得分:1)

如果不向控制器添加功能,可以使用指令

angular.module('myApp').directive('ticket-payment', [function() {
    return {
        template: '<div class="ticket-payment">payment options</div>',
        link: function(scope, element, attrs) {
            var status = attrs.status;
            var orgTicketId = attrs.orgTicketId;
            var balance = attrs.balance;

            if (status == 0 &&
              ((orgTicketId === '' && balance > 0) ||
              (orgTicketId !== '' && balance < 0))) {
                element.hide();
            }
        }
    };
});

至少你的HTML看起来会更清晰

<div ticket-payment
     status="{{ticket.status}}"
     orgTicketId="{{ticket.orgTicketId}}"
     balance="{{ticketControl.balance}}">
</div>

答案 2 :(得分:0)

&#13;
&#13;
ticketService.getTicket(123).then(
  function (ticket) {
    $scope.ticket = ticket;
    $scope.ticket.paymentsAllowed=IsPaymentsAllowed(ticket);
  });
//Define IsPaymentsAllowed function to return a bool value based on your condition
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您始终可以在控制器上定义逻辑,然后从模板中调用它,这样就可以获得实时可更新状态:

在您的模板上:

<div ng-show="isPaymentAllowed(ticket)">
    <!-- your html stuff -->
</div>

在您的控制器上:

$scope.isPaymentAllowed = function(ticketToCheck){
    // Put your logic here, returning true or false
    return true
}

当任何涉及的变量发生变化时,Angular会自动重新检查您的状态。

希望有所帮助

答案 4 :(得分:0)

您可以使用angular $resource提供程序,并结合继承。

angular.module('myApp').factory('Tickets', ['$resource', function($resource) {
    var Tickets = $resource('api/tickets/:ticketId');

    angular.extend(Tickets.prototype, {
        paymentsAllowed: function() {
            return this.status == 0 && 
                   ((this.orgTicketId === '' && this.balance > 0 ) || 
                   (this.orgTicketId !== '' && this.balance < 0));
        }
    }

    return Tickets;
});

现在,当你拿到一张票时,你会通过Tickets工厂

来完成
$scope.ticket = Tickets.get({ ticketId: 123 });

并且,在您看来:

<div ng-show="ticket.paymentsAllowed()"></div>

答案 5 :(得分:-1)

您可以使用$ watch-er

// update paymentAllowed when ticket changes
$scope.$watch('ticket', function(newValue, oldValue) {
    $scope.paymentAllowed = (newValue.status == 0 &&
                            ((newValue.orgTicketId === '' && newValue.balance > 0) ||
                            (newValue.orgTicketId !== '' && newValue.balance < 0)));
}, true);

最后的true参数告诉$watch ticket是一个对象,并且应该在触发之前执行深度比较。

然后你可以简单地使用paymentAllowed属性

<div ng-show="paymentAllowed"></div>