[解決済み] スコープをアンギュラーサービスにインジェクトする function()
質問
あるサービスがあります。
angular.module('cfd')
.service('StudentService', [ '$http',
function ($http) {
// get some data via the $http
var path = 'data/people/students.json';
var students = $http.get(path).then(function (resp) {
return resp.data;
});
//save method create a new student if not already exists
//else update the existing object
this.save = function (student) {
if (student.id == null) {
//if this is new student, add it in students array
$scope.students.push(student);
} else {
//for existing student, find this student using id
//and update it.
for (i in students) {
if (students[i].id == student.id) {
students[i] = student;
}
}
}
};
しかし
save()
を呼び出すと、私は
$scope
を取得し
ReferenceError: $scope is not defined
. ですから、論理的なステップとしては、(私にとって) save() に
$scope
を提供することであり、したがって、私はまた、それを
service
. だから、もし私がこのように
.service('StudentService', [ '$http', '$scope',
function ($http, $scope) {
以下のようなエラーが出ます。
エラーです。[$injector:unpr] 不明なプロバイダーです。$scopeProvider <- $scope <- です。 StudentService
エラーのリンクから、インジェクタ関連であること、また、jsファイルの宣言の順番に関係していることがわかりました。 私は
index.html
の中で順番を変えてみましたが、私が注入している方法など、もっと単純なものだと思います。
Angular-UIとAngular-UI-Routerを使用する。
どのように解決するのですか?
この
$scope
は、何らかのサービス (他の注入可能なものと同様) ではなく、スコープオブジェクトです。多くのスコープオブジェクトを作成することができます (通常は、親スコープをプロトタイプとして継承します)。すべてのスコープのルートは
$rootScope
であり、新しい子スコープを作成するには
$new()
メソッドを使って新しい子スコープを作ることができます (例えば
$rootScope
).
スコープの目的は、アプリのプレゼンテーションとビジネスロジックを接着させることです。このため
$scope
をサービスに渡すことはあまり意味がありません。
サービスは、データを共有したり (たとえば複数のコントローラ間で)、 一般に再利用可能なコードをカプセル化するために使用されるシングルトン オブジェクトです (コントローラ、ディレクティブ、フィルタ、他のサービスなど、 アプリケーションのどの部分にも注入してサービスを提供することができます)。
私は、さまざまなアプローチがあなたのために働くと確信しています。1つはこれです。
というのも
StudentService
は生徒のデータを扱う担当なので
StudentService
に学生の配列を保持させ、興味のありそうな人 (例えば、あなたの
$scope
). これは、その情報にアクセスする必要がある他のビュー/コントローラ/フィルタ/サービスがある場合、さらに理にかなっています(今はまだないとしても、すぐに現れ始めても驚かないようにしましょう)。
新しい生徒が追加されるたびに (サービスの
save()
メソッドを使用して)、サービス自身の学生の配列が更新され、その配列を共有する他のすべてのオブジェクトも同様に自動的に更新されます。
上記のアプローチに基づくと、あなたのコードは次のようになります。
angular.
module('cfd', []).
factory('StudentService', ['$http', '$q', function ($http, $q) {
var path = 'data/people/students.json';
var students = [];
// In the real app, instead of just updating the students array
// (which will be probably already done from the controller)
// this method should send the student data to the server and
// wait for a response.
// This method returns a promise to emulate what would happen
// when actually communicating with the server.
var save = function (student) {
if (student.id === null) {
students.push(student);
} else {
for (var i = 0; i < students.length; i++) {
if (students[i].id === student.id) {
students[i] = student;
break;
}
}
}
return $q.resolve(student);
};
// Populate the students array with students from the server.
$http.get(path).then(function (response) {
response.data.forEach(function (student) {
students.push(student);
});
});
return {
students: students,
save: save
};
}]).
controller('someCtrl', ['$scope', 'StudentService',
function ($scope, StudentService) {
$scope.students = StudentService.students;
$scope.saveStudent = function (student) {
// Do some $scope-specific stuff...
// Do the actual saving using the StudentService.
// Once the operation is completed, the $scope's `students`
// array will be automatically updated, since it references
// the StudentService's `students` array.
StudentService.save(student).then(function () {
// Do some more $scope-specific stuff,
// e.g. show a notification.
}, function (err) {
// Handle the error.
});
};
}
]);
この方法を使うときに注意しなければならないのは、サービスの配列を決して再代入しないことです。なぜなら、他のコンポーネント(例えばスコープ)が元の配列を参照したままになってしまい、アプリが壊れてしまうからです。
の配列をクリアするには、例えば
StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
参照:こちらも ショート・デモ .
LITTLE UPDATEです。
サービスを使用することについて話しているときに生じるかもしれない混乱を避けるために、いくつかの単語を
service()
関数で作成するのではありません。
を引用して
のドキュメントを引用しています。
$provide
:
アンギュラ サービス が作成するシングルトンオブジェクトです。 サービスファクトリ . これらは サービス工場 は関数であり、順番に サービスプロバイダ . そのため サービスプロバイダ はコンストラクタ関数です。インスタンス化されたとき、それらは
$get
と呼ばれるプロパティが必要です。 サービスファクトリ 関数を保持します。
[...]
...その$provide
サービスには、プロバイダを指定せずにサービスを登録するためのヘルパーメソッドが追加されています。
- provider(プロバイダ) - サービスプロバイダを $injector に登録します。
- 定数(obj) - は、プロバイダやサービスからアクセス可能な値/オブジェクトを登録します。
- 値(obj) - は、プロバイダではなく、サービスからのみアクセス可能な値/オブジェクトを登録します。
- ファクトリー(fn) - は、サービスプロバイダオブジェクトにラップされる、サービスファクトリ関数fnを登録します。
- サービス(クラス) - は、コンストラクタ関数、サービスプロバイダオブジェクトにラップされるクラス、その$getプロパティが与えられたコンストラクタ関数を使用して新しいオブジェクトをインスタンス化することを登録します。
基本的に、これはすべてのAngularサービスが
$provide.provider()
を使用しますが、よりシンプルなサービスのための "ショートカット"メソッドがあります(そのうちの2つは
service()
と
factory()
).
全てはサービスに帰結するので、どの方法を使っても(サービスの要件がその方法でカバーできる限り)大差はないのです。
ところで
provider
対
service
対
factory
はAngular初心者にとって最も混乱する概念の1つですが、幸いなことに、物事を簡単にするためのリソースが(ここSOに)たくさんあります(検索してみてください)。(検索してみてください)。
(これで解決することを願っています。解決しない場合は教えてください)
関連
-
[解決済み] 適用がすでに進行中のエラー
-
[解決済み] どのようにangularJSでrouteProviderとlocationProviderを設定するのですか?
-
[解決済み] AngularJS : ローカルストレージを使用する
-
[解決済み] AngularJSで画像を表示する
-
AngularJSのベストプラクティス。ng-repeatの$indexに注意する。
-
[解決済み] AngularJSを使用して、ブラウザのコンソールで$scope変数にアクセスするにはどうすればよいですか?
-
[解決済み] AngularJSで$scope.$watchと$scope.$applyを使用するにはどうすればよいですか?
-
[解決済み] angular-routeとangular-ui-routerの違いは何ですか?
-
[解決済み] AngularJS コントローラにおける 'this' と $scope の比較
-
[解決済み】AngularJSのディレクティブスコープにおける「@」と「=」の違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Angular ui-routerで$stateメソッドを$stateChangeStart toStateとfromStateで使用する。
-
[解決済み] angularのpostリクエストでpreflightのレスポンスがHTTPステータスコード403で不正になる。
-
[解決済み] X-Frame-Options'を'SAMEORIGIN'に設定しているため、フレーム内での表示を拒否された。
-
[解決済み] AngularJSの.$uibModalとは何ですか?
-
[解決済み] エラーです。10回の$digest()反復に達しました。動的なsortby述語で中断!?
-
[解決済み] AngularJS の ng-disabled ディレクティブに式を指定しても動作しない
-
[解決済み] ng-pattern` - 数字だけをチェックする方法は?
-
[解決済み] Angular JSによるシンプルなポップアップ
-
[解決済み] なぜAngularJSはselectに空のオプションを含めるのですか?
-
[解決済み] AngularJSのサービスをコンソールからテストするにはどうしたらいいですか?