私は AngularJS に比較的慣れていないので、Restangular を使用して AngularJS の CRUD メソッドを DRY に保つためのさまざまな方法を試してきたので、コミュニティからのアドバイスをいただければ幸いです。
多くの API エンドポイントがあり、それぞれに項目のリストを表示し、各項目を選択して (その項目の詳細を表示するために)、削除したり、項目をリストに追加したりしたいと考えています。
私がこれまでに試したアプローチはどれも、非常に非 DRY であるか、$scope に適切にフックされていないか、ややハッキーでした...
ラッピング逆角
Restangular をサービスにラップし、addElementTransformer を使用して返されたコレクションに追加のメソッドを設定することは、適切なアプローチのように思えました。select
メソッドとメソッドはクリーンで、add
テンプレートから簡単に実装でき、promise が解決されるとリストを自動的に更新します。ただし、delete
メソッドは実際には要素スコープ (コレクションの子) 内から呼び出されるため、削除後にリストを更新するには、非常に疑わしい $scope をサービスに注入する必要があります。
(注: 単一の API エンドポイント/コントローラー/テンプレートのみを示すことで、例を読みやすくしました)
アプリ/js/services.js
function ListTransformer(collection) {
collection.selected = {}
collection.assignedTo = {}
collection.assignedName = ""
collection.add = function(item) {
collection.post(item)
.then(function(response){
collection.push(response);
})
};
collection.delete = function(item, scope) {
item.remove()
.then(function(response){
console.log(item)
console.log(collection)
collection.assignedTo[collection.assignedName] = _.without(collection, item);
})
};
collection.select = function(item) {
this.selected = item;
};
collection.assignTo = function(scope, name) {
scope[name] = collection;
collection.assignedTo = scope
collection.assignedName = name
};
return collection;
};
angular.module('myApp.services', ['restangular'])
.factory('Company', ['Restangular',
function(Restangular){
var restAngular = Restangular.withConfig(function(Configurer) {
Configurer.addElementTransformer('companies', true, ListTransformer);
});
var _companyService = restAngular.all('companies');
return {
getList: function() {
return _companyService.getList();
}
}
}
])
app/js/controllers.js
angular.module('myApp.controllers', [])
.controller('CompanyCtrl', ['$scope', 'Company', function($scope, Company) {
Company.getList()
.then(function(companies) {
companies.assignTo($scope, 'companies'); // This seems nasty
});
}]);
アプリ/部分/会社.html
<ul>
<li ng-repeat="company in companies">
<a href="" ng-click="companies.select(company)">{{company.name}}</a> <a href="" ng-click="clients.delete(client)">DEL</a>
</li>
</ul>
<hr>
{{companies.selected.name}}<br />
{{companies.selected.city}}<br />
ベース コントローラの拡張
私が試した別のアプローチは、他のコントローラーが継承するベースコントローラーでテンプレートをサービスに接続することでした。ただし、ここではまだ $scope の問題があり、テンプレートからスコープを渡す必要がありますが、これは正しくないようです。
delete
(メソッドだけに編集)
アプリ/js/services.js
angular.module('myApp.services', ['restangular'])
.factory('ListController', function() {
return {
delete: function(scope, item, list) {
item.remove();
scope.$parent[list] = _.without(scope.$parent[list], item);
}
};
});
app/js/controllers.js
.controller('CompanyCtrl', ['$scope', 'ListController', 'Restangular', function($scope, ListController, Restangular) {
angular.extend($scope, ListController);
$scope.companies = Restangular.all('companies').getList();
}])
アプリ/部分/会社.html
<ul>
<li ng-repeat="company in companies">
<a href="" ng-click="companies.select(company)">{{company.name}}</a> <a href="" ng-click="delete(this, companies, company)">DEL</a>
</li>
</ul>
ディレクティブ
私はディレクティブに少し慣れていませんが、多くの調査の結果、これがおそらく最もAngularJSにアプローチする方法であると思われるので、飛び込みました。基本的に問題は、リストからアイテムを削除できますが、すべての変数をディレクティブに渡さない限り、リストが最初に割り当てられた $scope のプロパティにアクセスできないため、アクセスできないことです。ビューで更新します。
app/js/directives.js
angular.module('myApp.directives', [])
.directive('delete', function() {
return {
restrict: 'E',
replace: true,
template: '<button>Delete</button>',
link: function (scope, element, attrs) {
element.bind('click', function() {
var item = scope[attrs.item];
item.remove();
scope.$parent[attrs.from] = _.without(scope.$parent[attrs.from], item)
});
},
};
});
アプリ/部分/会社.html
<ul>
<li ng-repeat="company in companies">
<a href="" ng-click="companies.select(company)">{{company.name}}</a> <delete item="company" from="companies">
</li>
</ul>
基本的に、私はすべてを機能させることができますが、多くの繰り返しコードを実行するか (これは明らかに間違っています)、すべての呼び出しと共にスコープを送信するか (これも非常に間違っているようです)、またはサービスを初期化する必要があるようです。スコープを渡すことによって(私のコントローラーにとって最も適切なソリューションではありませんが、これを達成するための最も維持しやすく、最も脆弱な方法のようです.
もちろん、機能を削除するか、詳細ビューまたはチェックボックス/一括アクション機能に移動することもできますが、問題に夢中になり、最善の解決策を見つけることに興味がありました:)
明らかな何かが欠けている場合はお詫びします。