2013-07-10 9 views
7

AngularJSアプリケーションでselect2プラグインを使用して、いくつかのエンティティ(タグ)のリストを表示しています。これは私のテンプレートの一部です:AngularJSアプリケーションでselect2プラグインを使用

select.ddlTags(ui-select2="select2Options", multiple, ng-model="link.tags") 
     option(ng-repeat="tag in tags", value="{{tag.id}}") {{tag.name}} 

、これは私の範囲のコードの一部です:

$scope.select2Options = { 
    formatNoMatches: function(term) { 
    var message = '<a ng-click="addTag()">Добавить тэг "' + term + '"</a>' 
    console.log(message); 
    return message; 
    } 
} 

私はそれがタグリストに存在していない場合はすぐに新しいタグを追加する機能を提供したいです。そこで、formatNoMatchesのselect2オプションを上書きして、「新しいタグを追加」リンクを表示します。 addTag()関数を$ scopeからリンクのclickイベントに正しくバインドする方法はありますか?

+0

あなたはそれをスコープに追加できますか? ie。 $スコープ。addTag = function(){ } – insomiac

答えて

4

あなたがこの参照することができます:JS

var myApp = angular.module('myApp', ['ui.select2']); 

function MyCtrl($scope, $timeout) { 

    // Initialize with Objects. 
    $scope.tagsSelection = [{ 
     "id": "01", 
      "text": "Perl" 
    }, { 
     "id": "03", 
      "text": "JavaScript" 
    }]; 

    $scope.showDialog = function (item) { 
     console.log(item); // if you want you can put your some logic. 
    }; 

    $timeout(function() { 
     $scope.tagsSelection.push({ 
      'id': '02', 
       'text': 'Java' 
     }); 
    }, 3000); 

    $scope.tagData = [{ 
     "id": "01", 
      "text": "Perl" 
    }, { 
     "id": "02", 
      "text": "Java" 
    }, { 
     "id": "03", 
      "text": "JavaScript" 
    }, { 
     "id": "04", 
      "text": "Scala" 
    }]; 

    // to show some add item in good format 
    $scope.formatResult = function (data) { 
     var markup; 
     if (data.n === "new") markup = "<div> <button class='btn-success btn-margin'><i class='icon-plus icon-white'></i> Create :" + data.text + "</button></div>"; 
     else markup = "<div>" + data.text + "</div>"; 
     return markup; 

    }; 

    $scope.formatSelection = function (data) { 
     return "<b>" + data.text + "</b></div>"; 
    }; 

    $scope.tagAllOptions = { 
     multiple: true, 
     data: $scope.tagData, 
     tokenSeparators: [","], 
     createSearchChoice: function (term, data) { // this will create extra tags. 
      if ($(data).filter(function() { 
       return this.v.localeCompare(term) === 0; 
      }).length === 0) { 
       return { 
        id: term, 
        text: term, 
        n: "new", 
        s: "" 
       }; 
      } 
     }, 
     // initSelection: function(element, callback) { //if you want to set existing tags into select2 
    // callback($(element).data('$ngModelController').$modelValue); 
    // }, 
     formatResult: $scope.formatResult, 
     formatSelection: $scope.formatSelection, 
     dropdownCssClass: "bigdrop", 
     escapeMarkup: function (m) { 
      return m; 
     } 
    }; 



}; 

ワーキングフィドル

HTML

<div ng-controller="MyCtrl"> 
     <input ng-change="showDialog(tagsSelections)" type="text" ui-select2="tagAllOptions" ng-model="tagsSelections" style="width:300px;" /> 
     <pre> tagsSelection: {{tagsSelections | json}}</pre>   
</div> 

を: Quickly add a new tag

+0

Chromeで作業している作業フィドル29.未知のエラー:モジュールがありません:ui.select2 – TheSharpieOne

+0

解決策の問題(実際には元の問題です)は、「作成」ボタンがまだAngularのダイジェストサイクルから外れていて、新しく追加されたアイテムは角度が分からないままです。 – Manu

+0

select2ライブラリへの参照が壊れているため、Fiddleは機能しません。これは、jsFiddleによって許可されていないtext/plainのMIMEタイプを持つ生のGitHub参照です。 –

6

この問題の解決の鍵は、そのあなたです$コンパイルサービスを使用する必要がありますoptionsオブジェクトのformatNoMatches関数によって返されたHTMLにこのコンパイルのステップでは、マークアップのng-clickディレクティブがスコープに接続されます。残念ながら、これはやや簡単です。

あなたがここにフル実施例を参照することができます:私はAngularJSは、検索の結果を監視するためSELECT2コントロールを鑑賞するための知っている方法はありませんhttp://jsfiddle.net/jLD42/4/

、私たちは時にコントローラに通知しなければなりません結果は見つかりません。これはformatNoMatches関数を使用して行うのは簡単です:

$scope.select2Options = { 
    formatNoMatches: function(term) { 
     console.log("Term: " + term); 
     var message = '<a ng-click="addTag()">Add tag:"' + term + '"</a>'; 
     if(!$scope.$$phase) { 
      $scope.$apply(function() { 
       $scope.noResultsTag = term; 
      }); 
     } 
     return message; 
    } 
}; 

$scope.noResultsTagプロパティはマッチを返されていないユーザーが入力した最後の値を追跡します。 formatNoMatchesがAngularJSダイジェストループのコンテキスト外で呼び出されるため、$scope.noResultsTagへの更新を$ scope。$ applyでラップする必要があります。

我々は$scope.noResultsTagを見て、変更が発生したときformatNoMatchesマークアップをコンパイルすることができます

$scope.$watch('noResultsTag', function(newVal, oldVal) { 
    if(newVal && newVal !== oldVal) { 
     $timeout(function() { 
      var noResultsLink = $('.select2-no-results'); 
      console.log(noResultsLink.contents()); 
      $compile(noResultsLink.contents())($scope); 
     }); 
    } 
}, true); 

あなたは$タイムアウトが何をしているのか不思議に思うかもしれません。これは、formatNoMatchesマークアップでDOMを更新するselect2コントロールと、そのマークアップをコンパイルしようとするウォッチ関数との間の競合状態を回避するために使用されます。それ以外の場合は、$('.select2-no-results')セレクタが探しているものを見つけられず、コンパイルステップでコンパイルするものがない可能性があります。

追加タグリンクがコンパイルされると、ng-click指示文はコントローラのaddTag関数を呼び出すことができます。あなたはjsFiddleでこれを見ることができます。 [タグを追加]リンクをクリックすると、タグ配列がselect2コントロールに入力した検索用語で更新され、次回select2コントロールに新しい検索用語を入力するときにマークアップとオプションリストに表示されます。

+0

うまくいくと思われます。私はこの問題に苦しんできました。ありがとう! –