CREATEコントローラーとEDITコントローラーの間には重複したコードがたくさんあります。これらのコントローラーを1つに組み合わせて、繰り返しのコードを最小限に抑えることができます。
問題:フォームの送信に使用するメソッドを区別する必要があります-たとえば、create()またはedit()。
解決策:たとえば、$scope.mode
を追加し、ユーザーが[編集]ボタンをクリックした場合は$scope.mode='edit'
を設定し、ユーザーが[追加]ボタンをクリックした場合は$scope.mode='add'
を設定できます。
繰り返しのコードを最小限に抑えるためのサービスを使用できますが、重複するコードは残ります。たとえば、両方のコントローラーに、フォームをクリアして非表示にするcancel()メソッドがあります。 clearForm()とhideForm()をサービスに格納できますが、このコードは両方のコントローラーで複製されます。
$scope.cancel = function() {
Service.clearForm();
Service.hideForm();
};
質問:
はい。 1つのコントローラーを使用します。
これが1つのコントローラーを使用する理由です
コントローラの役割は、ビューをサポートすることです。作成ビューと編集ビューはまったく同じです。一方にはデータが事前入力されており(編集)、もう一方にはデータが入力されていない(作成)だけです。さらに、このビューの「目的」は、ユーザーにフォームに新しい値を変更または入力させることです。唯一の違いはreset()のようなものです。しかし、そこでさえ、空のモデルオブジェクトから始めることができます。 CREATEの場合は_$scope.entity = {}
_で、$scope.entity = $http.get()
から始めます。
2つのコントローラーでの繰り返しの問題
2つの異なるコントローラーとサービスを使用すると、少なくとも次の重複が発生します。
_$scope.cancel = function() {
Service.cancel();
};
$scope.validate = function() {
ValidtionSvc.validate();
}
.
.
.//other stuff similar
_
しかし問題は、あなたが述べたようなこの重複でさえなぜかということです。
(上記が最初の質問への回答だったので、ここ以降はUDATED)
1つのコントローラーを繰り返し使用する方法は?
繰り返しのコードを最小限に抑えるための良い習慣はありますか?
質問の再定義:CREATEフォームとEDITフォームで繰り返されるコードを削除する良い方法はありますか?
この特定の状況でコードが繰り返されるのを避けるための正式な「ベストプラクティス」は私の知る限り存在しません。ただし、mode = edit/createには反対することをお勧めします。この状況でのコントローラーの理由は、ユーザーが対話するときにモデルをフェッチ/更新することだけが仕事であるため、ほとんど違いがないはずです。
この状況で発生する違いと、mode = create/editを使用してif/then/elseを回避する方法は次のとおりです。
1)フォームに既存の値を入力するか、Createの空のフォームを入力します。
既存のエンティティをフェッチするには、いくつかのキー/クエリデータが必要です。そのような重要なデータが存在する場合、あなたはすることができます
_var masterEntity = {};
if(keyData) {
masterEntity = MyEntityResourceFactory.getEntity(keyData);
}
$scope.entity = masterEntity;//for Create this would be {}
_
2)reset()フォームは単純でなければなりません
_ $scope.reset = function() {
$scope.entity = masterEntity;
}
_
3)更新/作成
_$http.post()//should not be different in today's world since we are treating PUT as POST
_
4)検証-これは完全な再利用です-違いはないはずです。
5)初期/デフォルト値
{}の代わりにmasterEntity = Defaultsを使用できます。
AngularJSでCREATEコントローラーとEDITコントローラーを組み合わせるのは良い習慣ですか?
私の経験では、そうです、99.9%の確率でそれは良い考えです。私は通常、formType変数を$ routeProvider解決機能を介してコントローラーに挿入します。だから私は次のようなものを持っているでしょう:
$routeProvider
.when('/item/create', {
templateUrl: '/app/item/itemForm.html',
controller: 'itemFormController',
resolve: {
item: ['$route', 'itemRepository', function ($route, itemRepository) {
return itemRepository.getNew();
}],
formType: function () { return Enums.FormType.CREATE; }
},
})
.when('/item/edit/:itemId', {
templateUrl: '/app/item/itemForm.html',
controller: 'itemFormController',
resolve: {
item: ['$route', 'itemRepository', function ($route, itemRepository) {
return itemRepository.get($route.current.params.itemId);
}],
formType: function () { return Enums.FormType.EDIT; },
},
});
このようにして、エンティティとフォームアクションのタイプをコントローラーに注入します。同じテンプレートも共有しているので、フォームを保存する場合は、リポジトリ/サービスを使用して呼び出すRESTエンドポイントを決定するか、挿入されたformTypeに応じてコントローラー内で簡単なチェックを行うことができます。
繰り返しのコードを最小限に抑えるための良い習慣はありますか?
私が物事を乾いた状態に保つために使用しているもののいくつか:
サーバーAPIで共通の規則を維持している場合は、データアクセス用の基本ファクトリ/リポジトリ/クラス(呼び出したいものは何でも)を使用して非常に長い道のりを進むことができます。例えば:
GET -> /{resource}?listQueryString // Return resource list
GET -> /{resource}/{id} // Return single resource
GET -> /{resource}/{id}/{resource}view // Return display representation of resource
PUT -> /{resource}/{id} // Update existing resource
POST -> /{resource}/ // Create new resource
etc.
次に、基本リポジトリクラスを返すAngularJsファクトリを使用し、それをabstractRepository
と呼びます。次に、リソースごとに、abstractRepositoryからプロトタイプ的に継承する特定のリソースの具象リポジトリを作成します。そのため、abstractRepositoryからすべての共有/ベース機能を継承し、リソース固有の機能を具象リポジトリに定義します。このようにして、データアクセスコードの大部分をabstractRepositoryで定義できます。 Restangularを使用した例を次に示します。
abstractRepository
app.factory('abstractRepository', [function () {
function abstractRepository(restangular, route) {
this.restangular = restangular;
this.route = route;
}
abstractRepository.prototype = {
getList: function (params) {
return this.restangular.all(this.route).getList(params);
},
get: function (id) {
return this.restangular.one(this.route, id).get();
},
getView: function (id) {
return this.restangular.one(this.route, id).one(this.route + 'view').get();
},
update: function (updatedResource) {
return updatedResource.put();
},
create: function (newResource) {
return this.restangular.all(this.route).post(newResource);
}
// etc.
};
abstractRepository.extend = function (repository) {
repository.prototype = Object.create(abstractRepository.prototype);
repository.prototype.constructor = repository;
};
return abstractRepository;
}]);
具体的なリポジトリ、例として顧客を使用しましょう:
app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) {
function customerRepository() {
abstractRepository.call(this, restangular, 'customers');
}
abstractRepository.extend(customerRepository);
return new customerRepository();
}]);
このベースリポジトリパターンを使用すると、ほとんどのCRUDコントローラーも多くの共通コードを共有するため、通常、コントローラーが継承するベースCRUDコントローラーを作成します。ベースコントローラーのアイデアが気に入らない人もいますが、私たちの場合はそれも役立っています。
最初の質問に対する答えは、おそらく特定の状況によって異なります。
2つのコントローラーがかなりの量の操作を共有し、1つまたは2つの関数の動作を変更する必要がある場合は、どうしてですか。おそらく最もエレガントな解決策ではありませんが、うまくいくものは何でもねえ。
多くまたはすべてのコントローラー操作の動作が「$ scope.mode」に依存する場合は...注意が必要です。それは危険な道のようです。
Angularサービスは、コントローラー間のコードレプリケーションを最小限に抑えるという点で常に役に立ちました。 「反復コードを最小限に抑えるためのグッドプラクティス」があれば、それはサービスだと思います。これらはアプリに対してグローバルであり、問題なく複数のコントローラーに挿入できます。
お役に立てば幸いです。