서비스가 있습니다 :
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
서비스 에을 전달하는 것은 의미가 없습니다 .
서비스는 데이터를 공유 (예 : 여러 컨트롤러간에)하고 일반적으로 재사용 가능한 코드 조각을 캡슐화하는 데 사용되는 싱글 톤 객체입니다 (컨트롤러, 컨트롤러, 컨트롤러, 지시문, 필터, 기타 서비스 등).
다양한 접근 방식이 도움이 될 것이라고 확신합니다. 하나는 이것이다.이 ( 가) 학생 데이터를 처리
하기 때문에 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); }
이 짧은 데모 도 참조하십시오 .
약간의 업데이트 :
서비스 사용에 대해 이야기 할 때 발생할 수있는 혼동을 피하기 위해 몇 마디 말하지만 service()
기능으로 만들지는 않습니다.
에 대한 문서$provide
인용 :
Angular 서비스 는 서비스 팩토리에서 만든 단일 개체입니다 . 이러한 서비스 팩토리 는 서비스 제공 업체에 의해 생성되는 기능입니다 . 서비스 제공자는 생성자 함수입니다. 인스턴스화되면 서비스 팩토리 기능
$get
을 보유하는 라는 속성을 포함해야합니다 .
[…]
… 서비스에는 공급자를 지정하지 않고 서비스를 등록하는 추가 도우미 메서드가 있습니다.
$provide
- provider (provider) -$ injector에 서비스 제공자 등록
- constant (obj) -공급자 및 서비스에서 액세스 할 수있는 값 / 객체를 등록합니다.
- value (obj) -공급자가 아닌 서비스에서만 액세스 할 수있는 값 / 객체를 등록합니다.
- factory (fn) -$ get 속성이 주어진 팩토리 함수를 포함하는 서비스 공급자 객체에 래핑 될 서비스 팩토리 함수 fn을 등록합니다.
- service (class) -$ get 속성이 지정된 생성자 함수를 사용하여 새 개체를 인스턴스화하는 서비스 공급자 개체에 래핑 될 클래스 인 생성자 함수를 등록합니다.
기본적으로 모든 Angular 서비스는를 사용하여 등록 $provide.provider()
되지만 더 간단한 서비스를위한 “바로 가기”방법이 있습니다 (그 중 두 가지는 service()
및 factory()
).
이 모든 것이 서비스에 “보이기”때문에 어떤 방법을 사용하든 큰 차이가 없습니다 (서비스 요구 사항이 해당 방법으로 처리 될 수있는 한).
BTW, provider
vs service
vs factory
는 Angular 신규 사용자에게 가장 혼란스러운 개념 중 하나이지만 다행스럽게도 작업을 더 쉽게 할 수있는 많은 리소스 (여기 SO)가 있습니다. (그냥 주변을 검색하십시오.)
(그게 해결되기를 바랍니다. 그렇지 않은 경우 알려주세요.)
답변
$scope
서비스 내에서 수정을 시도하는 대신 $watch
컨트롤러 내에서를 구현 하여 서비스의 속성에서 변경 사항을 확인한 다음 $scope
. 다음은 컨트롤러에서 시도 할 수있는 예입니다.
angular.module('cfd')
.controller('MyController', ['$scope', 'StudentService', function ($scope, StudentService) {
$scope.students = null;
(function () {
$scope.$watch(function () {
return StudentService.students;
}, function (newVal, oldVal) {
if ( newValue !== oldValue ) {
$scope.students = newVal;
}
});
}());
}]);
한 가지 유의해야 할 점은 students
속성이 표시 되려면 서비스 내에서 속성이 Service 개체에 this
있어야합니다.
this.students = $http.get(path).then(function (resp) {
return resp.data;
});
답변
글쎄 (긴 것) … 서비스 내에서 액세스 권한 을 주장 하는 경우 다음 을 수행 $scope
할 수 있습니다.
게터 / 세터 서비스 만들기
ngapp.factory('Scopes', function (){
var mem = {};
return {
store: function (key, value) { mem[key] = value; },
get: function (key) { return mem[key]; }
};
});
그것을 주입하고 그 안에 컨트롤러 범위를 저장하십시오
ngapp.controller('myCtrl', ['$scope', 'Scopes', function($scope, Scopes) {
Scopes.store('myCtrl', $scope);
}]);
이제 다른 서비스 내에서 범위를 가져옵니다.
ngapp.factory('getRoute', ['Scopes', '$http', function(Scopes, $http){
// there you are
var $scope = Scopes.get('myCtrl');
}]);
답변
서비스는 싱글 톤이며 범위가 서비스에 삽입되는 것은 논리적이지 않습니다 (실제로 서비스에 범위를 삽입 할 수 없음). 범위를 매개 변수로 전달할 수 있지만 이는 잘못된 디자인 선택입니다. 여러 위치에서 범위를 편집하여 디버깅하기 어렵 기 때문입니다. 범위 변수를 처리하기위한 코드는 컨트롤러에 있어야하고 서비스 호출은 서비스로 이동해야합니다.
답변
서비스가 범위를 완전히 인식하지 못하도록 만들 수 있지만 컨트롤러에서 범위를 비동기 적으로 업데이트 할 수 있습니다.
당신이 겪고있는 문제는 당신이 http 호출이 비동기 적으로 이루어진다는 것을 모르기 때문에 당신이 할 수있는 것처럼 즉시 값을 얻지 못한다는 것을 의미합니다. 예를 들어
var students = $http.get(path).then(function (resp) {
return resp.data;
}); // then() returns a promise object, not resp.data
이 문제를 해결하는 간단한 방법이 있으며 콜백 함수를 제공하는 것입니다.
.service('StudentService', [ '$http',
function ($http) {
// get some data via the $http
var path = '/students';
//save method create a new student if not already exists
//else update the existing object
this.save = function (student, doneCallback) {
$http.post(
path,
{
params: {
student: student
}
}
)
.then(function (resp) {
doneCallback(resp.data); // when the async http call is done, execute the callback
});
}
.controller('StudentSaveController', ['$scope', 'StudentService', function ($scope, StudentService) {
$scope.saveUser = function (user) {
StudentService.save(user, function (data) {
$scope.message = data; // I'm assuming data is a string error returned from your REST API
})
}
}]);
형식 :
<div class="form-message">{{message}}</div>
<div ng-controller="StudentSaveController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<input type="button" ng-click="reset()" value="Reset" />
<input type="submit" ng-click="saveUser(user)" value="Save" />
</form>
</div>
이것은 간결성을 위해 비즈니스 로직 중 일부를 제거했으며 실제로 코드를 테스트하지는 않았지만 이와 같은 것이 작동합니다. 주요 개념은 컨트롤러에서 나중에 호출되는 서비스로 콜백을 전달하는 것입니다. NodeJS에 익숙하다면 이것은 동일한 개념입니다.
답변
같은 곤경에 빠졌습니다. 나는 다음과 같이 끝났다. 그래서 여기서는 범위 객체를 공장에 주입하는 것이 아니라 $ http 서비스에서 반환 한 promise 의 개념을 사용하여 컨트롤러 자체에 $ scope 를 설정합니다 .
(function () {
getDataFactory = function ($http)
{
return {
callWebApi: function (reqData)
{
var dataTemp = {
Page: 1, Take: 10,
PropName: 'Id', SortOrder: 'Asc'
};
return $http({
method: 'GET',
url: '/api/PatientCategoryApi/PatCat',
params: dataTemp, // Parameters to pass to external service
headers: { 'Content-Type': 'application/Json' }
})
}
}
}
patientCategoryController = function ($scope, getDataFactory) {
alert('Hare');
var promise = getDataFactory.callWebApi('someDataToPass');
promise.then(
function successCallback(response) {
alert(JSON.stringify(response.data));
// Set this response data to scope to use it in UI
$scope.gridOptions.data = response.data.Collection;
}, function errorCallback(response) {
alert('Some problem while fetching data!!');
});
}
patientCategoryController.$inject = ['$scope', 'getDataFactory'];
getDataFactory.$inject = ['$http'];
angular.module('demoApp', []);
angular.module('demoApp').controller('patientCategoryController', patientCategoryController);
angular.module('demoApp').factory('getDataFactory', getDataFactory);
}());
답변
범위 변수를 처리하기위한 코드는 컨트롤러에 있어야하고 서비스 호출은 서비스로 이동해야합니다.
당신은 삽입 할 수 $rootScope
사용을 목적으로 $rootScope.$broadcast
하고 $rootScope.$on
.
그렇지 않으면 주입을 피하십시오 $rootScope
. 보다