2

Iam doing serverside validation in dynamicly created input fields that resides within tags. Problem is that I need to return the API error message back to my template, not set it directly in my controller. If I set it in my controller it will affect all input fields.

My plan is to do something like this:

#Template
..<span ng-show="innerNameForm.name.$error.apiResponse">{{ msg }}</span>


..<input type="text" ng-change="msg = someFunction(inputValue, innerNameForm)"...... />

#Controller
scope.someFunction = function(value, form){

    apiMsg = timeout(function() {

        var prom = vcRecordValidate.name(value, record_id).then(function(promise){

            //If fails... do this
            form.name.$setValidity('apiResponse', false);... 
            return promise; //THis contains the API error message

        });
        
        return prom;

    }, 1000);

    return apiMsg;

};

Code is just an example, and is missing some unimportant stuff..

Question is.. how can I return the promise-data back to my template?

Community
  • 1
  • 1
JoakimB
  • 1,196
  • 2
  • 13
  • 19

2 Answers2

1

You don't "return" data through promises. You fulfil promises with data. You need to invoke promise.resolve(data) to pass data to your callbacks.

user229044
  • 232,980
  • 40
  • 330
  • 338
  • Can you perhaps put together a small example that maps to my case? – JoakimB Sep 12 '13 at 18:55
  • Not really, your case doesn't seem to make any sense. I can't tell what you're trying to do at all. – user229044 Sep 12 '13 at 19:18
  • In a normal case this situation would be solved by using a scope var with the promise response.. however each of my input fields are dynamicly created and are inside an .. therefore I cant do that.. if I do it effects all fields since they share the same innerForm name. Each inneForm is its own childScope and therefore I want to return the promise back to that specific scope. Only way I found to do this is to return data from the function I execute from the template and save the response in a variable.. the ng-change example in my initial question. – JoakimB Sep 12 '13 at 19:25
0

Angular supports the display of a model from the $scope when it's a promise.

$scope.load = function (i) {
  var deferred = $q.defer();
  $timeout(function () {
     deferred.resolve('done with ' + i + ' !');
  }, 3000);
  return deferred.promise;
}
...
<span ng-repeat="item in items">{{load($index)}}</span>

But this can be tricky and generate recursive and maybe infinite $apply calls. If I were you I would just display a subvar of every item in my array

<span ng-repeat="item in items">{{item.asyncResult}}</span>

and asynchronously trigger the load of every item like this for instance

$timeout(function () {
  angular.forEach($scope.items, function (item, idx) {
    item.asyncResult = 'done with ' + idx + ' !';
  });
}, 3000);

And to deal with multiple inputs with the same name inside a given form, since Angular does not support dynamic names for form inputs, I would suggest you to use nested ng-form with the same name (see this question for details).

Community
  • 1
  • 1
ovmjm
  • 1,624
  • 12
  • 15
  • Thanks for replying, however.. Iam not following you.. you gave me examples that dont map to my example at all.. can you please look at my example and explain this according to that? – JoakimB Sep 12 '13 at 19:13
  • To summary : use nested forms to prevent input names collisions (I added a link at the end of my answer), then don't use timeout but $timeout which will automagically wrap your function inside a $apply, finally if you really want to use promise, use them as shown in my example, or use a nested msg field inside the items of your array. If required I can help you to fix a jsFiddle if you care starting one. – ovmjm Sep 12 '13 at 19:23
  • Well I use nested forms and this works like a charm when doing client-side validation.. like using the required or pattern directive. However if I wanna $setValidity on this specific field from the controller its another story. Also regarding $timeout.. I use that one but wrapped in a function. – JoakimB Sep 12 '13 at 19:30
  • Here is a jsFiddle with a working example using promises. But again. If I were you I would not use promises in this case. http://plnkr.co/edit/HqPYrU4v4CpaajWw285A?p=preview – ovmjm Sep 12 '13 at 19:58
  • I got this to work. deffered to me atm is pure magic.. I must learn how and why this work.. can you please comment why using a promise in this case isnt a good idea? Thanks! – JoakimB Sep 12 '13 at 20:46
  • I'm not sure how ng-change is working but you can imagine that ng-change creates a promise, when the promise is resolved it triggers a apiCheck again (because it is a function) which in turn creates a promise, and so on... this is particularly true when doing this {{foo()}} with foo that returns a promise, maybe it's safe with ng-change, but I prefer updating a model when the promise is resolved this is more state oriented. – ovmjm Sep 12 '13 at 20:54