tokenInput as angular.js directive
Asked Answered
C

4

7

I'm attempting to create an angular.js directive from James Smith's tokenInput Jquery plugin: http://loopj.com/jquery-tokeninput

Here is what I have so far:

antdna = angular.module('Communication', []);

antdna.factory('autoCompleteService', [function() {
    return {
      getSource: function() {
      return [{"id":1, "name":"John Doe"}, {"id":2, "name":"Jane Smith"}];
    }
  }
}]);

antdna.directive('autoComplete', function(autoCompleteService) {
    return {
        restrict: 'A',
        link: function(scope, elem) {
            elem.tokenInput(autoCompleteService.getSource(), {
                crossDomain:false,
                theme: "facebook",
                hintText: "Enter User Name",

                preventDuplicates: true
            });
            }
    };
});

With the following markup:

<input type="text" name="recipient" ng-model="conversation.recipients" class="messageComposeTextField" auto-complete placeholder="To :" required />

TokenInput works perfectly but my issue is that I cannot bind to the model.

{{conversation.recipients}} 

is blank.

The tokenInput plugin generates it's own markup using list elements (ul and li). So upon inspecting the element I get:

<ul class="token-input-list-facebook">
  <li class="token-input-token-facebook"><p>John Doe</p><span class="token-input-delete-token-facebook">×</span></li><li class="token-input-input-token-facebook"><input type="text" autocomplete="off" autocapitalize="off" id="token-input-" style="outline: none; width: 30px;"><tester style="position: absolute; top: -9999px; left: -9999px; width: auto; font-size: 12px; font-family: Ubuntu, 'Ubuntu Beta', UbuntuBeta, Ubuntu, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, sans-serif; font-weight: 400; letter-spacing: 0px; white-space: nowrap;"></tester>    </li>
</ul>

<input type="text" name="recipient" ng-model="conversation.recipients" class="messageComposeTextField ng-pristine ng-invalid ng-invalid-required" auto-complete="" placeholder="To :" required="" style="display: none;">

Notice that the generated tokenInput markup is not part of the directive. So the real question here is how do I encapsulate a jquery plugin that generates its own markup within an angularjs directive?

Cellobiose answered 26/8, 2013 at 11:37 Comment(0)
W
3

I suggest you to use ui-select2 ready to use directive for similar functionality @ https://github.com/angular-ui/ui-select2, it provides "simple tagging mode" similar to your requirement

Check the new example. The old example can be found here.

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

$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"
    }
];

$scope.tagAllOptions = {
    multiple: true,
    data: $scope.tagData
};

You can check details for options and documentation at: http://ivaynberg.github.io/select2/

Westlund answered 26/8, 2013 at 11:52 Comment(4)
Thank you for the suggestion, I can't seem to get your fiddle to workCellobiose
Apologies, it's a Chrome thing with the MIME type. Works fine in FFCellobiose
Select2 worked a treat, just needed to add the ajax option to pull user data off my server. Thank you for you helpCellobiose
your are checking in which browser. In FF it is working fine i have just check itWestlund
C
10

Following up @JqueryGuru suggestion, perhaps you'd be interested in taking a look at a tags input directive I've implemented recently: ngTagsInput. It's 100% Angular code and has several configuration options. You can see some demos here.

Cyrilla answered 26/8, 2013 at 13:57 Comment(6)
Thanks, but I'm looking into using it with autocomplete too. Like Gmail adding recipients where it autocompletes when you start typing a nameCellobiose
No problem. That feature is on the roadmap. Given time, it'll be implemented eventually. :)Cyrilla
Is there anywhere to click for donations on your site? I may not have much money at present but I would like to donate.Vladamar
@Zehelvion No, there's no donation button at the moment. I appreciate your intention to donate, though. :)Cyrilla
@MichaelBenford since you are being so nice, I noticed that the model in the demo looks like {text: ironman, text: wonderwoman, text: spiderman} and was wondering if I could tell it I want another key name instead? Many thanksVladamar
@Zehelvion Use the displayProperty option to set the property you want the directive to use.Cyrilla
W
3

I suggest you to use ui-select2 ready to use directive for similar functionality @ https://github.com/angular-ui/ui-select2, it provides "simple tagging mode" similar to your requirement

Check the new example. The old example can be found here.

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

$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"
    }
];

$scope.tagAllOptions = {
    multiple: true,
    data: $scope.tagData
};

You can check details for options and documentation at: http://ivaynberg.github.io/select2/

Westlund answered 26/8, 2013 at 11:52 Comment(4)
Thank you for the suggestion, I can't seem to get your fiddle to workCellobiose
Apologies, it's a Chrome thing with the MIME type. Works fine in FFCellobiose
Select2 worked a treat, just needed to add the ajax option to pull user data off my server. Thank you for you helpCellobiose
your are checking in which browser. In FF it is working fine i have just check itWestlund
R
0

I had similar issues and while the alternate plugin and Angular own tag directives are very interesting, I was not able to change the token-input plugin because of some project requirements, therefore I added model update logic into the Add/Delete configuration variables of Token Input plugin.

The Code:

vehicleModule.directive('tokenInput', function ($rootScope,$parse, $http){
return {
    restrict: 'A',
    link: function(scope, elem, attr, ctrl) {
        var prepopMailsJson = getElementsAsJson(elem.attr('value'));            
        elem.tokenInput(applicationRootUrl +"rest/firmwareManager/getAvailableVehicles", {
            prePopulate: prepopMailsJson,
            theme: "facebook",
            minChars: 2,
            resultsLimit: 12,
            propertyToSearch: "id",
            resultsFormatter: function(item){ 
                var name = "";
                if(typeof(item.name) != 'undefined' && item.name != null){
                    name = item.name;
                }
                return "<li>" + "<div style='display: inline-block; padding-left: 10px;'><div class='id'>" + item.id + "</div></div></li>"; 
            },
            tokenFormatter: function(item) { 
                return "<li><p>" + item.id + "</p></li>"; 
            },
            hintText: vehicleTokenInputTranslation.hintText,
            noResultsText: vehicleTokenInputTranslation.noResultsText,
            searchingText: vehicleTokenInputTranslation.searchingText,
            preventDuplicates: true,
            queryParam: "partialName",
            tokenLimit: 1,
            onAdd : function(item){                 
                scope.vehicleId = item.id;
            },
            onDelete : function(item){
                scope.vehicleId = '';
                scope.$apply();
            }
        });

    }
};


});

This way, you only need to use the token-input directive in your input element and it will work. This can be made even more generic by passing the model variable name in the attr. I hope this code is useful to people that have issues integrating JqueryUI Token-Input and AngularJS.

Riddick answered 8/5, 2014 at 20:21 Comment(0)
I
0

For people who are required to use the loopj token-input for whatever reason, this gist worked perfectly for me. I found it to be kind of cryptic though, since I'm not very experienced with Angular and he only had 2 comments, so here's what I've figured out about how to use it.

You include the top level jquery module like:

angular.module('myModule', ['jquery'])

In the html you have:

<input token-input="source">

In the javascript you have:

$scope.source = {/* data */};
$scope.tokenInput = {/* options */}

If you want to have several with different options, it looks like you could also do something like:

<input id="id" token-input="source">
$scope.source = {/* data */};
$scope.tokenInput_id = {/* options */}
Interception answered 21/4, 2015 at 16:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.