Search code examples
angularjsng-tags-input

Getting angular tags input to work


I am trying to implement ng-tags-input to work within my website, so basically people need to input some tags by choosing tag(s) from a list of available tags persisted on database

server:

exports.list = function(req, res) {

  var query = req.query;
  mongoose.set('debug', true);

  Tag
    .find({
      'text': new RegExp(query.text, 'i')
    })
    .sort({
      created: -1
    })
    .select('text')
    .exec(function(err, tags) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        console.log('Tags: ', tags);
        res.json(tags);
      }
    });
};

angular controller:

(function() {
  'use strict';

  angular
    .module('contests')
    .controller('ContestsAddController', ContestsAddController);

  ContestsAddController.$inject = [
    '$scope',
    '$state',
    '$location',
    'Tag'
  ];

  function ContestsAddController(
    $scope,
    $state,
    $location,
    Tag
  ) {
    var vm = this;

    /** Properties */
    vm.tags = [];

    /** Methods */
    vm.loadTags = loadTags;

    function loadTags(query) {
      return Tag.load();
    }
  }
}());

view:

<div class="form-group">
  <label class="col-md-3 control-label">With tags </label>
  <div class="col-md-9">
    <tags-input ng-model="vm.tags" add-from-autocomplete-only="true">
      <auto-complete source="vm.loadTags($query)" debounce-delay="500" load-on-empty="true"></auto-complete>
    </tags-input>
  </div>
</div>

angular service:

(function() {
  'use strict';

  angular
    .module('tags')
    .factory('Tag', Tag);

  Tag.$inject = [
    '$http',
    '$q',
    '$timeout',
    'Authentication',
    'Shuttle',
    'CONST'
  ];

  function Tag(
    $http,
    $q,
    $timeout,
    Authentication,
    Shuttle,
    CONST
  ) {

    var service = {
      getTags: getTags,
      load: load
    };
    var _this = this;

    return service;

    // SCOPE FUNCTIONS
    function getTags(query) {
      return Shuttle.get(CONST.EP_TAGS, query, {}, 1000, {
        Authorization: 'JWT ' + Authentication.token
      });
    }

    function load() {
      var deferred = $q.defer();
      deferred.resolve(this.getTags({}));
      return deferred.promise;
    }
  }
}());

Tag.load() response

[  
  {  
    "_id":"579ecc5fca552b6e89094415",
    "text":"Comedian"
  },
  {  
    "_id":"579ecc5aca552b6e89094414",
    "text":"Cardist"
  },
  {  
    "_id":"579ecc56ca552b6e89094413",
    "text":"Magician"
  },
  {  
    "_id":"579ecc4bca552b6e89094412",
    "text":"Actress"
  },
  {  
    "_id":"579ecc47ca552b6e89094411",
    "text":"Actor"
  },
  {  
    "_id":"579ecbecca552b6e89094410",
    "text":"Bassist"
  },
  {  
    "_id":"579ecbdfca552b6e8909440f",
    "text":"Guitarist"
  },
  {  
    "_id":"579ecbd9ca552b6e8909440e",
    "text":"Singer"
  },
  {  
    "_id":"579ecbc6ca552b6e8909440d",
    "text":"Dancer"
  }
]

The problems that i am facing is that when i typed 3 letters (which correctly triggered Tag.load() as expected, and returning above's response)

  • it doesn't show any auto complete or tag suggestions
  • it's immediately putting that 3 letters as a tag (picture below)
  • the console.log(vm.tags); is not including the whole Tag object, just the text key value pair

enter image description here

is there something i missed?

i am using angular 1.5.0

UPDATE

I have added a plunker although with some modifications, but it is working just fine there, though it still doesn't work in my app, is it angular version?

One more thing i forgot to mention, the one's in mine is not showing the dropdown as i typed.

UPDATE #2 I updated the plunker using angular 1.5.0 which is the one i am using, and its working, so its not angular version.


Solution

  • So after trying out a few things, i finally got it working by doing this

    I reserved the Tag.getTags response object in a variable and call it on load rather than calling it every time user typed (or using the load-on-focus and or load-on-empty parameters) and using the filter method based on this example

    controller

    (function() {
      'use strict';
    
      angular
        .module('contests')
        .controller('ContestsAddController', ContestsAddController);
    
      ContestsAddController.$inject = [
        '$scope',
        '$state',
        '$location',
        'Tag',
        'toaster',
        'lodash'
      ];
    
      function ContestsAddController(
        $scope,
        $state,
        $location,
        Tag,
        toaster,
        lodash
      ) {
        var vm = this;
    
        /** Properties */
        vm.tagList = [];
        vm.tags = [];
    
        /** Methods */
        vm.loadTags = loadTags;
    
        function loadTags($query) {
          return vm.tagList.filter(function(tag) {
            return tag.text.toLowerCase().indexOf($query.toLowerCase()) !== -1;
          });
        }
    
        activate();
    
        function activate() {
          return _getTagList();
        }
    
        function _getTagList() {
          Tag
            .getTags()
            .then(function(response) {
              vm.tagList = response.data;
              return vm.tagList;
            });
        }
      }
    }());
    

    view (dont know if this is related)

    <tags-input ng-model="vm.tags" display-property="text" add-from-autocomplete-only="true" text="text">
      <auto-complete source="vm.loadTags($query)" debounce-delay="500"></auto-complete>
    </tags-input>