1

我正在构建一种仓库应用程序,其中包含项目余额。

由于与 AngularJS 相比,WinJS 似乎是一个巨大的痛苦,我决定尝试将两者结合起来。

我可以很好地将东西添加到我的数据库中,然后删除它们并显示它们。但是对于我的生活,我不知道如何在添加或删除新项目时更新项目列表。有人能帮忙吗?还是您认为我应该使用AngularJs以外的其他东西?

你能帮忙的话,我会很高兴

4

2 回答 2

0

我尝试对您的代码进行一些修改,以便让您更清楚。

这是一个现场演示:http ://plnkr.co/edit/bqOdx6ZREFNewohDMB9F?p=preview

首先:如果您需要在启动 Angular 应用程序之前进行配置,请在您的app.run. (请注意,我不熟悉 WinJS)。

var app = angular.module('plunker', []);

app.run(function() {
  WinJS.Binding.optimizeBindingReferences = true;

  var winapp = WinJS.Application;
  var activation = Windows.ApplicationModel.Activation;

  winapp.onactivated = function (args) {..};
  winapp.oncheckpoint = function (args) {...};

  var client = new WindowsAzure.MobileServiceClient(
    "https://skafferidb.azure-mobile.net/",
    "MFnbMHzNGgysVZIFIcHPLgLLRuJkxl87"
  );
});

或者如果你不能,像你做的那样做,但是在你准备好之后手动引导 Angular 。

第二:如果您需要访问数据库,请使用工厂来包装您的调用,以使它们在您的应用程序中可重用。在这里,我试图用假工厂模仿你的成分数据库查询。

app.factory('DbIngredients', function($q, $timeout) {

  var ingredients = [
    {id:1, name:'Banana', sum: 1, unit: 3},
    {id:2, name:'Apple', sum: 2, unit: 1},
    {id:3, name:'Orange', sum: 3, unit: 2},
  ];

  var maxid = 1000;

  return {
    getTable: function() {
      var deferred = $q.defer();

      $timeout(function() {
        deferred.resolve(ingredients);
      }, 1000);

      return deferred.promise; 
    },
    insert: function(item) {
      var deferred = $q.defer();

      $timeout(function() {
        item.id = maxid++;
        ingredients.push(item);
        deferred.resolve(ingredients);
      }, 1000);

      return deferred.promise;
    },
    remove: function(item) {
      var deferred = $q.defer();

      $timeout(function() {
        var chance = Math.random() >= 0.25;
        var index = ingredients.indexOf(item);
        if (chance && index >= 0) {
          ingredients.splice(index, 1);
          deferred.resolve(ingredients);
        } else {
          deferred.reject("Error: Remove!");
        }
      }, 1000);

      return deferred.promise;
    }
  }
});

我使用$qand$timeout服务创建了一个延迟承诺来模拟对数据库的远程调用。在这里,您将用您自己的数据库调用替换该$timeout部分,并且在该调用的响应中,您将通过deferred.resolvedeferred.reject如果发生错误将其数据发送到您的控制器。

第三:使用控制器中的工厂。由于我们从工厂调用返回了延迟承诺,我们必须等待异步响应。你可以使用then它来实现这两个函数:第一个是成功回调(deferred.resolve),第二个是错误回调(deferred.reject)。

app.controller('MainCtrl', function($scope, $timeout, DbIngredients, DbUser, DbUnits) {
  // ...

  DbIngredients.getTable().then(function(response) {
    $scope.ingredients = response;
  });

  DbUser.getDisplayNameAsync().then(function (response) {
    $scope.username = response;
  })

  DbUnits.getTable().then(function(response) {
    $scope.units = response;
  });

  // ...
});

当您收到响应时,您可以将它放在您的范围变量中以使用您视图中的值。

第四:您尝试在向数据库中插入和删除成分之前进行表单验证。Angular 内置了很好的表单验证功能,它使我们的生活更容易执行验证。

例如,您验证了成分在点击事件中具有名称、总和和单位。在 Angular 中,您可以使用字段ng-required="true|false"上的指令input来强制一个值。表单中每个字段的状态都可以通过 trough 访问formName.fieldName.$valid|$invalid|$dirty|$pristine。有关更多信息,请参阅文档

<form name="formctrl" class="addingredientform">
    <h2>{{username}}s Skafferi</h2>
    <input type="text" ng-model="newingredient.name" ng-required="true" placeholder="Råvara"/>
    <input type="number" ng-model="newingredient.sum" min="0" ng-required="true" placeholder="Antal" id="num"/>
    <select ng-model="newingredient.unit" ng-options="units.indexOf(unit) as unit for unit in units" ng-required="true">
    </select>
    <input type="number" ng-model="newingredient.bestbefore" placeholder="Bäst före (ÅÅÅÅMMDD)" />
    <button ng-click="addIngredient(newingredient)" ng-disabled="formctrl.$invalid">Add</button>
    <span ng-show="formctrl.$dirty && formctrl.$invalid" class="errormessage">Form is invalid!</span>
</form>

在这里,我ng-required在您的字段上添加了指令,并在表单为时禁用了button使用ng-disabled指令添加$invalid(任何无效的字段都会使整个表单无效)。此外,当表单无效并且 $dirty(已被修改)时,我会显示一条错误消息。如果您查看ng-model您的字段,我创建了一个newingredient对象并映射了字段并将该对象作为参数发送到 àddIngredient` 函数。

当且仅当表单有效时,我们才能从ng-click添加按钮中输入此功能。我们收到newingredient对象并调用工厂来插入它。然后,我们等待我们放回范围变量中的响应(角度会自动更新视图,因为它会监视任何更改)。

$scope.addIngredient = function (newingredient) {
    $scope.sending = "Adding...";
    DbIngredients.insert(newingredient).then(function (response) {
      $scope.ingredients = response;
        $scope.sending += " Success...";
        $timeout(function() { $scope.sending = ""; }, 1000);
    });
    $scope.formctrl.$setPristine();
    $scope.newingredient = {};
}

现在,它还取决于您对数据库的调用将返回什么,如果它只返回插入的对象而不是再次返回整个列表,您可能必须重新调用 getTable 或将对象推送到现有列表中($scope.ingredients.push(newingredient)) . 最后,我们将表单重置为其$pristine状态并清空newingredient对象。

第五:我们为去除成分做了类似的事情。

<div ng-repeat="ingredient in ingredients" class="listingredient">
    {{ingredient.name}}
    <input type="text" ng-model="ingredient.sum" placeholder="{{ingredient.sum}}" class="num" />
    {{units[ingredient.unit]}} 
    <button ng-click="removeIngredient(ingredient)">Remove</button>
  </div>

这是您可以从 Promise 接收到的成功和错误回调的示例。为了模拟错误,调用失败的可能性为 25%。

$scope.removeIngredient = function (ingredient) {
    $scope.sending = "Removing...";
    DbIngredients.remove(ingredient).then(
      // success
      function(response) {
        $scope.ingredients = response;
        $scope.sending += " Success...";
        $timeout(function() { $scope.sending = ""; }, 1000);
      },
      // error
      function(response) {
        $scope.sending += response;
        $timeout(function() { $scope.sending = ""; }, 1000);
      }
    );
}

我希望这能给你一些帮助!如果您有任何问题,请告诉我。

于 2013-10-13T20:39:49.750 回答
0

您最初是在populateList函数中填充列表,如下所示:

$scope.ingredients = ingFromDb.dataSource._list._keyMap;

因此,您的列表将具有约束力$scope.ingredients。在addIngredientorsaveIngredient函数中,您还应该更新$scope.ingredients数组,而不仅仅是将新添加的成分保存到后端。

于 2013-10-13T19:56:59.257 回答