2015-10-14 3 views
9

私のアプリでangular-bootstrap-colorpickerを使用していますが、奇妙な問題があります。カラーピッカーモジュールにはSliderという名前の工場があります。私のアプリにもSliderというファクトリがあるので、それはcolorpickerを動作させません。アプリケーションでこれが発生するたびにリファクタリングすることは不可能で、とにかくちょっとした回避策のように思えます。スローされるエラーは、私のアプリの工場は何の方法setSaturationを持っていないと角が「混乱」されているので、私は結論付けましたサードパーティの工場でMy Appの工場と同じ名前で干渉しないようにする

Uncaught TypeError: Slider.setSaturation is not a function

があります。私は工場について、そしてAngularがどのように組織化しているかについては十分に分かっていませんが、そうしたモジュールを介して利用できることは非常に奇妙なようです。例えば

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

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

またはその逆の影響を受けています。

私はSlider工場に干渉しないように、このカラーピッカーをコンパートメント化することができますか?

編集:

私は名前空間接頭辞としての使用はスマートなアイデアであるとリンクの答えに同意します。しかし、それは非現実的な量のリファクタリングを必要とするでしょう。私は以下の答えを感謝しますが、それは私が行動に移せるように十分に洗練されていません。

1)これは実際には(プロジェクトの先頭からのプレフィックスを除いて)最良の解決策ですか? - 私がこのような変更を行った場合、次回にバウアーアップデートをしたとき、または誰かが私のプロジェクトをプルダウンしてバウアーをインストールしたときに消去されますか?

2)良い方法がありますか? - そうでない場合は、現在の回答を拡大し、何が起こったのかの説明を追加できますか?

+1

上の例であるあなたは、あなたの工場の名前を変更する必要があります-partyモジュール。"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

2つの '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と接続しています。問題は、Angularはモジュールのインスタンシエーションごとに1つの$ injectorインスタンスしか持たず、定義されたすべての注入可能オブジェクトがそこに入るということです。注射可能なオブジェクトとは、定数、値、サービス、コントローラ、ディレクティブのことです。これは、最終的にそれらの間に複数のモジュールと依存関係を定義してアプリケーションをモジュール化しても、同じコンテキスト/名前空間/インジェクタ。

Angularはこのような場合にはfail-fastテクニックを使用しないことによってさらに悪化します。また、アプリケーションが動作し続けるため、高価なリファクタリングが頻繁に発生することがあります。そして、私たちがこれをどのように改善することができるのかという疑問が残っていますが、IMOの失敗は少なくともこの問題を回避するのに役立ちます。

あなたの場合、ライブラリは本当に小さく、必要なのはカラーピッカーの指示だけです。私はインスタンス化されたライブラリモジュール$ injectorからその定義を取っている間に、モジュール内のカラーピッカーディレクティブを定義することで回避策の例をhereにしました。このように、名前を変更することも自由です。:)

コード例:明確化の目的のために

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

同じ名前の2つのサービスを定義するときにどのように振る舞うの角を示す例もあります。アプリケーションは、最後のサービス定義で正常に動作し続けます。

私は、この回答によって物事がはっきりし、問題を解決することを願っています。より多くのご質問がある場合はお気軽にお問い合わせください。乾杯!

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という2つのファクトリを登録しています。

SameFactを私のコントローラから参照すると、最後に登録された工場、つまり工場がsecondAppになります。

しかし、モジュールfirstAppにある工場を手動で参照することはできます。

angular.injector(['module_name'])を使用して、必要なモジュールのインジェクタを選択し、get()ファンクションを使用して工場またはサービスを取得することができます。

結論

だから、あなたはcolorpickerモジュールのごSlide工場にその時点のスコープの変数を宣言する必要があります。 colorpickerモジュール内のすべての必要な操作を取得するには、このスコープ変数を使用します。関数が呼び出されている場所をcolorpickerに置き換え、この新しい変数に置き換えます。

これはあなたの現在の状況から生き残るために役立ちます。

このことについて疑問をお持ちですか?あなたのモジュールの初期化時に、スライダーの工場を含むだ、あなたのモジュールを先行

0

場所colorpicker.module:あなたはその三分の一を使用したい場合はここで

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

js fiddle