Chciałbym dodać kilka funkcji narzędziowych do mojej aplikacji AngularJS. Na przykład:
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
Czy najlepiej to zrobić, aby dodać je jako usługę? Z tego, co przeczytałem, mogę to zrobić, ale chciałbym użyć ich na swoich stronach HTML, więc czy nadal jest to możliwe, jeśli są w usłudze? Na przykład mogę użyć następującego:
<button data-ng-click="doSomething()"
data-ng-disabled="isNotString(abc)">Do Something
</button>
Czy ktoś może mi podać przykład, jak mógłbym je dodać. Powinienem stworzyć usługę, czy jest na to inny sposób. Co najważniejsze, chciałbym, aby te funkcje narzędziowe znajdowały się w pliku, a nie w połączeniu z inną częścią głównej konfiguracji.
Rozumiem, że istnieje kilka rozwiązań, ale żadne z nich nie jest tak jasne.
Rozwiązanie 1 - zaproponowane przez Urbana
$scope.doSomething = ServiceName.functionName;
Problem w tym, że mam 20 funkcji i dziesięć kontrolerów. Gdybym to zrobił, oznaczałoby to dodanie dużej ilości kodu do każdego kontrolera.
Rozwiązanie 2 - zaproponowane przeze mnie
var factory = {
Setup: function ($scope) {
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
Wadą tego jest to, że na początku każdego kontrolera miałbym jedno lub więcej wywołań Instalatora do każdej usługi, która przeszła przez zakres $ scope.
Rozwiązanie 3 - zaproponowane przez Urbana
Dobrze wygląda rozwiązanie zaproponowane przez urbanistę polegające na stworzeniu usługi generycznej. Oto moja główna konfiguracja:
var app = angular
.module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
.config(['$locationProvider', '$sceProvider', '$stateProvider',
function ($locationProvider, $sceProvider, $stateProvider) {
$sceProvider.enabled(false);
$locationProvider.html5Mode(true);
Czy powinienem dodać do tego usługę ogólną i jak mogę to zrobić?
Odpowiedzi:
EDYCJA 7/1/15:
Napisałem tę odpowiedź dość dawno temu i od jakiegoś czasu niewiele nadążam za angularem, ale wygląda na to, że ta odpowiedź jest nadal stosunkowo popularna, więc chciałem zwrócić uwagę, że kilka punktów @nicolas sprawia, że poniżej są dobre. Po pierwsze, wstrzyknięcie $ rootScope i dołączenie tam pomocników pozwoli uniknąć konieczności dodawania ich dla każdego kontrolera. Ponadto - zgadzam się, że jeśli to, co dodajesz, powinno być traktowane jako usługi Angular LUB filtry, to należy je zaadaptować do kodu w ten sposób.
Ponadto, od aktualnej wersji 1.4.2, Angular udostępnia API „Provider”, które może być wstrzykiwane do bloków konfiguracyjnych. Zobacz te zasoby, aby uzyskać więcej informacji:
https://docs.angularjs.org/guide/module#module-loading-dependencies
Wstrzyknięcie zależności od AngularJS wartości wewnątrz module.config
Nie sądzę, żebym zaktualizował rzeczywiste bloki kodu poniżej, ponieważ obecnie nie używam aktywnie Angular i nie chcę ryzykować nowej odpowiedzi bez poczucia komfortu, że faktycznie dostosowuje się do nowego najlepszego praktyki. Jeśli ktoś inny czuje się na siłach, zrób to.
EDYCJA 2/3/14:
Po przemyśleniu tego i przeczytaniu niektórych innych odpowiedzi wydaje mi się, że wolę odmianę metody przedstawioną przez @Brent Washburne i @Amogh Talpallikar. Zwłaszcza jeśli szukasz narzędzi takich jak isNotString () lub podobnych. Jedną z wyraźnych zalet jest to, że możesz ich ponownie używać poza swoim kodem kątowym i możesz ich używać wewnątrz funkcji konfiguracyjnej (czego nie możesz zrobić z usługami).
Biorąc to pod uwagę, jeśli szukasz ogólnego sposobu ponownego wykorzystania tego, co powinno być usługami, myślę, że stara odpowiedź jest nadal dobra.
To, co bym teraz zrobił, to:
app.js:
controller.js:
Następnie w części możesz użyć:
Stara odpowiedź poniżej:
Najlepiej byłoby uwzględnić je jako usługę. Jeśli zamierzasz ponownie użyć ich na wielu kontrolerach, w tym jako usługa, unikniesz konieczności powtarzania kodu.
Jeśli chcesz korzystać z funkcji usług w części html, powinieneś dodać je do zakresu tego kontrolera:
$scope.doSomething = ServiceName.functionName;
Następnie w części możesz użyć:
Oto sposób, w jaki możesz to wszystko zorganizować i uniknąć zbytniego kłopotu:
Podziel swój kontroler, usługę i kod / konfigurację na trzy pliki: controllers.js, services.js i app.js. Moduł górnej warstwy to „aplikacja”, która zawiera kontrolery aplikacji i usługi aplikacji jako zależności. Następnie app.controllers i app.services można zadeklarować jako moduły we własnych plikach. Ta struktura organizacyjna pochodzi właśnie z Angular Seed :
app.js:
services.js:
controller.js:
Następnie w części możesz użyć:
W ten sposób dodajesz tylko jedną linię kodu do każdego kontrolera i masz dostęp do dowolnej funkcji usług, gdziekolwiek ten zakres jest dostępny.
źródło
Wracając do tego starego wątku, chciałem to podkreślić
1 °) funkcje narzędziowe można (należy?) Dodać do zakresu głównego za pośrednictwem module.run. W tym celu nie ma potrzeby instalowania określonego kontrolera poziomu głównego.
2 °) Jeśli organizujesz swój kod w oddzielne moduły, powinieneś użyć angular usług lub fabryki, a następnie wstrzyknąć je do funkcji przekazanej do bloku uruchamiania, w następujący sposób:
3 °) Rozumiem, że w widokach w większości przypadków te funkcje pomocnicze są potrzebne do zastosowania pewnego rodzaju formatowania do wyświetlanych ciągów. W tym ostatnim przypadku potrzebujesz filtrów kątowych
A jeśli ustrukturyzowałeś niektóre metody pomocnicze niskiego poziomu w usługach kątowych lub fabryce, po prostu wstrzyknij je w konstruktorze filtrów:
Twoim zdaniem:
źródło
run
-czasu. A co z czasem konfiguracji? Czy nie potrzebujemy tam narzędzi?Czy dobrze rozumiem, że chcesz po prostu zdefiniować niektóre metody narzędziowe i udostępnić je w szablonach?
Nie musisz ich dodawać do każdego kontrolera. Po prostu zdefiniuj jeden kontroler dla wszystkich metod narzędziowych i dołącz ten kontroler do <html> lub <body> (używając dyrektywy ngController). Wszystkie inne kontrolery, które dołączysz w dowolnym miejscu pod <html> (czyli gdziekolwiek, kropka) lub <body> (gdziekolwiek poza <head>) odziedziczą ten $ scope i będą miały dostęp do tych metod.
źródło
<div class="main-container" ng-controller="UtilController as util">
wtedy w dowolnych widokach wnętrza:<button ng-click="util.isNotString(abc)">
Najłatwiejszym sposobem dodania funkcji narzędziowych jest pozostawienie ich na poziomie globalnym:
Następnie najprostszym sposobem dodania funkcji użytkowej (do kontrolera) jest przypisanie jej do
$scope
, na przykład:Następnie możesz to nazwać tak:
lub tak:
EDYTOWAĆ:
Pierwotne pytanie brzmi, czy najlepszym sposobem dodania funkcji narzędzia jest usługa. Mówię nie, jeśli funkcja jest wystarczająco prosta (jak
isNotString()
przykład dostarczony przez OP).Zaletą pisania usługi jest zastąpienie jej inną (poprzez wstrzyknięcie) w celu testowania. Doprowadzając do skrajności, czy musisz wstrzyknąć każdą funkcję narzędzia do kontrolera?
Dokumentacja mówi, aby po prostu zdefiniować zachowanie w kontrolerze (np.
$scope.double
): Http://docs.angularjs.org/guide/controllerźródło
Oto prosta, zwarta i łatwa do zrozumienia metoda, której używam.
Najpierw dodaj usługę w swoim js.
Następnie w kontrolerze wstrzyknij obiekt pomocniczy i użyj dowolnej dostępnej funkcji z czymś podobnym do następującego:
źródło
Możesz również skorzystać z usługi stałej jako takiej. Zdefiniowanie funkcji poza stałym wywołaniem umożliwia również jej rekurencję.
źródło
Dlaczego nie skorzystać z dziedziczenia kontrolera, wszystkie metody / właściwości zdefiniowane w zakresie HeaderCtrl są dostępne w kontrolerze wewnątrz ng-view. $ scope.servHelper jest dostępny we wszystkich twoich kontrolerach.
źródło