我正在构建一种仓库应用程序,其中包含项目余额。
由于与 AngularJS 相比,WinJS 似乎是一个巨大的痛苦,我决定尝试将两者结合起来。
我可以很好地将东西添加到我的数据库中,然后删除它们并显示它们。但是对于我的生活,我不知道如何在添加或删除新项目时更新项目列表。有人能帮忙吗?还是您认为我应该使用AngularJs以外的其他东西?
你能帮忙的话,我会很高兴
我尝试对您的代码进行一些修改,以便让您更清楚。
这是一个现场演示: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;
}
}
});
我使用$q
and$timeout
服务创建了一个延迟承诺来模拟对数据库的远程调用。在这里,您将用您自己的数据库调用替换该$timeout
部分,并且在该调用的响应中,您将通过deferred.resolve
或deferred.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);
}
);
}
我希望这能给你一些帮助!如果您有任何问题,请告诉我。
您最初是在populateList
函数中填充列表,如下所示:
$scope.ingredients = ingFromDb.dataSource._list._keyMap;
因此,您的列表将具有约束力$scope.ingredients
。在addIngredient
orsaveIngredient
函数中,您还应该更新$scope.ingredients
数组,而不仅仅是将新添加的成分保存到后端。