アイテムの残高を保持する一種の倉庫アプリを構築しています。
WinJS は AngularJS に比べて非常に面倒に思えるので、両方を組み合わせて試してみることにしました。
データベースに問題なく追加したり、削除したり、表示したりできます。しかし、私の人生では、新しいアイテムが追加または削除されたときにアイテムのリストを更新する方法がわかりません。誰でもこれを手伝ってもらえますか?それとも、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 をブートストラップします。
2 つ目:データベースにアクセスする必要がある場合は、ファクトリを使用して呼び出しをラップし、アプリケーション全体で再利用できるようにします。ここでは、偽のファクトリを使用して Ingredients データベース クエリを模倣しようとしました。
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
およびサービスを使用$timeout
して、データベースへのリモート呼び出しをシミュレートする deferred promise を作成しました。ここで、パーツを独自のデータベース呼び出しに置き換え、$timeout
その呼び出しの応答で、deferred.resolve
またはdeferred.reject
エラーが発生した場合にそのデータをコントローラーに送信します。
3 番目:コントローラーでファクトリを使用します。ファクトリ呼び出しから延期された promise を返したので、非同期応答を待つ必要があります。これを行うには、2 つの関数を使用then
できます。1 つ目は成功コールバック (deferred.resolve)、2 つ目はエラー コールバック (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;
});
// ...
});
応答を受け取ったら、それをスコープ変数に入れて、ビューで値を使用できます。
4 番目:成分をデータベースに挿入および削除する前に、フォームの検証を実行しようとしました。Angular には優れたフォーム検証機能が組み込まれており、検証の実行が非常に簡単になります。
たとえば、成分がクリック イベントで名前、合計、および単位を持っていることを検証しました。angularでは、フィールドでng-required="true|false"
ディレクティブを使用しinput
て値を強制できます。フォーム内のすべてのフィールドの状態は、 からアクセスできます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
て追加を無効にしました (無効なフィールドはフォーム全体を無効にします)。また、フォームが無効な場合 (変更されている場合) にエラー メッセージを表示します。フィールドを見ると、オブジェクトを作成してフィールドをマッピングし、このオブジェクトをパラメーターで àaddIngredient` 関数に送信しています。button
ng-disabled
$invalid
$dirty
ng-model
newingredient
フォームが有効な場合にのみng-click
、追加ボタンからこの関数に入ることができます。オブジェクトを受け取り、newingredient
ファクトリを呼び出して挿入します。次に、スコープ変数に戻す応答を待ちます (angular は変更を監視するため、自動的にビューを更新します)。
$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
ます。
5番目:材料の除去についても同様のことを行います.
<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);
}
);
}
これがあなたの助けになったことを願っています!ご不明な点がございましたら、お知らせください。