2015-10-14 3 views
9

Я использую angular-bootstrap-colorpicker в своем приложении и имею странную проблему. В модуле colorpicker есть фабрика с именем Slider. Это приводит к тому, что colorpicker не работает, потому что у моего приложения также есть фабрика под названием Slider. Рефакторинг каждого случая этого в приложении невозможен, и в любом случае это похоже на небрежное обходное решение. Ошибка броска являетсяПредотвращение фабрики сторонних производителей с использованием фабрики моего приложения с тем же именем

Uncaught TypeError: Slider.setSaturation is not a function

который я пришел к выводу, потому что завод моего приложения не имеет никакого метода setSaturation и Угловые является «путать». Я не знаю достаточно о фабриках и как Angular их организует, но кажется странным, что они будут доступны в таких модулях. например

angular.module('thomasApp', []) 
... 
.factory('Slider', ... 

влияет

angular.module('colorpicker.module', []) 
... 
.factory('Slider', ... 

или наоборот.

Есть ли какой-нибудь способ разделить этот цветной указатель так, чтобы он не мешал моей фабрике Slider?

Edit:

Я согласен с ответом, который связан с использованием префикса в качестве пространства имен является смарт-идея. Однако для этого потребуется нереалистичный объем рефакторинга. Я благодарен за ответ ниже, но для меня это недостаточно, чтобы я мог действовать.

1) Это действительно лучшее решение (кроме префикса от начала проекта)? - Если я сделаю такое изменение, оно будет удалено в следующий раз, когда я обновляю bower, или кто-то вытащит мой проект и установит bower install?

2) Есть ли лучший способ? - Если нет, можно ли расширить текущий ответ и объяснить, что происходит?

+1

Вы должны переименовать завод, если вы хотите использовать эту треть -партийный модуль.Я рекомендую использовать префикс типа «thomasSlider» или просто «thSlider». Вы также можете использовать такие периоды, как этот «thomas.Slider», но вам придется использовать массивные инъекции, чтобы передать его функции. – cgTag

+0

@ThinkingMedia Действительно ли я не могу просто переименовать части стороннего модуля? – 1252748

+0

Возможный дубликат [Модули и конфликты имен/имен в AngularJS] (http://stackoverflow.com/questions/13406791/modules-and-namespace-name-collision-in-angularjs) – fracz

ответ

5

Возможно, что-то вроде этого - создайте поддельный модуль и заверните существующего провайдера под новым именем. Это изолирует зависимость.

var colorpicker = angular.module('my-colorpicker', ['colorpicker.module']); 
 
colorpicker.factory('ColorPickerSlider', function() { 
 
    var injector = angular.injector(['colorpicker.module']); 
 
    var Slider = injector.get('Slider'); 
 
    return Slider; 
 
});

Я знаю, что это не решает основную проблему пространств имен, но это дает способ скрыть существующие зависимости в песочнице.

+0

У вас все еще есть две службы Slider. – zeroflagL

+0

@zeroflagL Вы правы. Вот почему я упомянул в своем ответе, что он не отвечает на вопрос о конфликте пространства имен. Я бы хотел, чтобы был упрощенный способ этого. – FrailWords

+0

@zeroflagL Angular2 имеет «useClass» для решения этой проблемы - https://angular.io/docs/ts/latest/api/core/Provider-class.html, но не уверен, как или если его можно портировать на Angular 1. Икс. – FrailWords

7

Проблема, которая у вас есть, уже известна в Angular. @fracz был прав, он связан с Modules and namespace/name collision in AngularJS. Проблема заключается в том, что у Углового есть только один экземпляр инжектора на один экземпляр модуля и все определенные инъекционные объекты входят в него. Под инъекционными объектами я подразумеваю константы, значения, службы, контроллеры, директивы. Это плохо в тех случаях, когда это происходит, потому что, даже если мы модулизируем наше приложение, определяя несколько модулей и зависимости между ними в конце, все определенные инъективные объекты оказываются в один и тот же контекст/пространство имен/инжектор.

Угловой делает это еще хуже, если не использовать fail-fast техники в таких случаях, и поскольку приложение продолжает работать, вы можете в конце концов заметить проблему, которая часто может привести к дорогостоящим рефакторингам. И все еще возникает вопрос, как мы можем это улучшить, ИМО неудачно, по крайней мере, поможет избежать этой проблемы в ее начале.

Однако в вашем случае вам повезло, что библиотека действительно маленькая, и вам нужна только директива выбора цвета. Я сделал обходной пример here, указав директиву выбора цвета в вашем модуле, взяв его определение из инстанцированного библиотечного модуля $ injector. Таким образом, вы можете изменить свое имя :).

Пример кода:

// NOTE: redefine the directive 
app.directive('colorpicker', function() { 
    var injector = angular.injector(['ng', 'colorpicker.module']); 
    return injector.get('colorpickerDirective')[0]; 
}); 

В целях разъяснения есть также пример, который показывает, как угловые ведет себя при определении двух службы с тем же именем. Приложение успешно продолжает работу с последним определением службы.

Надеюсь, что этот ответ прояснит ситуацию и успешно решает вашу проблему. Если у вас есть еще вопросы, не стесняйтесь спрашивать. Ура!

0

Да, вы можете обрабатывать несколько заводов с одинаковым именем.

Вот пример,

var app = angular.module('firstApp', []); 
app.factory('SameFact', [function() { 
    return { Name: "First" }; 
}]); 

var app2 = angular.module('secondApp', ['firstApp']); 

app2.factory('SameFact', [function() { 
    return { Name: "Second" }; 
}]); 

app2.controller("testController", ["SameFact", "$scope", "$injector", function (SameFact, $scope, $injector) { 
    $scope.myName = {}; 
    $scope.myName.Name1 = SameFact.Name; // This will be "Second", Last factory 
    var inj = angular.injector(['firstApp']); 
    $scope.my_inject = inj.get('SameFact').Name; // This will be "First", the first factory 
}]); 

Примечание

При передаче завода в качестве зависимости от контроллера, он будет регистрировать последний зарегистрированный завод.

То есть, в этом примере, я зарегистрировал два завода с одинаковым именем SameFact, но в другом модуле.

Когда я обращаюсь к фабрике SameFact с моего контроллера, он всегда укажет на завод, который зарегистрирован последним, т. Е. Завод в secondApp.

Но вы можете вручную указать завод, который находится в модуле firstApp.

Вы можете использовать angular.injector(['module_name']), чтобы выбрать инжектор вашего необходимого модуля, а затем использовать функцию get() внутри нее, чтобы получить завод или услугу.

Заключение

Итак, вам нужно объявить переменную области действия, которые указывают на ваш Slide завод colorpicker модуля. И используйте эту переменную области, чтобы получить все необходимые операции в модуле colorpicker. Найдите место, где вы вызываете функции colorpicker, и замените его на эту новую переменную.

Надеюсь, это поможет вам пережить вашу нынешнюю ситуацию.

Не стесняйтесь спрашивать об этом !!!

0

Место colorpicker.module предшествующих ваш модуль, который содержащий Slider завод, в вашей инициализации модуля:

angular.module('thomasApp', ['colorpicker.module','anotherModule'])

Вот пример на js fiddle

Смежные вопросы