Search code examples
angularjsfirebaseangularfireng-tags-input

Angular + Firebase Application - ngTagsInput Error: Cannot read property of 'data' undefined


I am using ng-tags-input to add Tagging to an Angular + Firebase Application.

I am running into the following error when trying to utilize autocomplete to auto-populate tags from a firebaseArray which pulling values of existing tags stored in my firebase at /tags

ERROR

TypeError: Cannot read property 'data' of undefined

Here is my Code...

HTML

<div class="form-group">
      <label for="inputTags" class="col-lg-2 control-label">Tags</label>
      <div class="col-lg-3">
        <tags-input ng-model="post.tags" >
          <auto-complete source="loadTags()"
                     min-length="1"
                     load-on-focus="true"
                     load-on-empty="true"
                     max-results-to-show="32"></auto-complete>
        </tags-input>
    </div>
</div>

JAVASCRIPT

$scope.loadTags = function() {
      var tagsArray = ['test']; //simply a test value
      var tagsRef = new Firebase(FIREBASE_URL + 'tags');
      tagsRef.once('value').then(function(snapshot) {
          // The Promise was "fulfilled" (it succeeded).
          console.log('Promise was fulfilled');

          // handle data
          angular.forEach (snapshot.val(), function(tag) {
            tagsArray.push(tag.name);
          });

          console.log(tagsArray);
          return tagsArray
        }, function(error) {
          // The Promise was rejected.
          console.log('Promise was rejected');
          console.error(error);
      });
      //return tagsArray;  <-- This Works, but doesn't include firebaseArray values
    };

As you can see, I am using the latest Firebase version (2.4.0) and using Promises in my firebase query... if you look at the console output you will see where the promise is being fulfilled after the error is triggered...

TypeError: Cannot read property 'data' of undefined
    at ng-tags-input.js:590
    at processQueue (angular.js:14792)
    at angular.js:14808
    at Scope.$eval (angular.js:16052)
    at Scope.$digest (angular.js:15870)
    at Scope.$apply (angular.js:16160)
    at angular.js:17927
    at completeOutstandingRequest (angular.js:5552)
    at angular.js:5829(anonymous function) @ angular.js:12520(anonymous function) @ angular.js:9292processQueue @ angular.js:14800(anonymous function) @ angular.js:14808Scope.$eval @ angular.js:16052Scope.$digest @ angular.js:15870Scope.$apply @ angular.js:16160(anonymous function) @ angular.js:17927completeOutstandingRequest @ angular.js:5552(anonymous function) @ angular.js:5829

posts.controller.js:15 Promise was fulfilled
posts.controller.js:22 ["test", "firebase", "javascript", "node.js", "angular.js", "bower.js", "npm", "angular.js", "bootstrap"]

QUESTION?

Is there a way to configure ng-tags-input to run asynchronously and only load values once the promise if fulfilled?

I would appreciate any help or suggestions.

Cheers! @FellowHobbyist


Solution

  • ngTagsInput can handle promises just fine. All you need to do is return a promise from your loadTags function:

    $scope.loadTags = function() {
      var tagsRef = new Firebase(FIREBASE_URL + 'tags');
      return tagsRef.once('value').then(function(snapshot) {
          console.log('Promise was fulfilled');
    
          var tagsArray = ['test'];
          angular.forEach (snapshot.val(), function(tag) {
            tagsArray.push(tag.name);
          });
    
          console.log(tagsArray);
          return tagsArray;
        }, function(error) {
          console.log('Promise was rejected');
          console.error(error);
          return $q.reject(); // <== This is important!
      });
    };
    

    Also notice the $q.reject() that I've included in your code. When you provide an error callback, you must return a rejected promise otherwise the promise as a whole will be considered fulfilled.