0

I'm using ng-repeat to generate a table (for example):

<table ng-repeat="item in items">
  <tr>
      <td>
          <input ng-blur="changeMyItem($event)">{{item.Name}}</input>
      <td>
      <td>
          <div>{{itemError}}</div>
      </td>
  </tr>
</table>

I am making a call that could potentially fail and I am having a hard time figuring out how to set itemError above to the error message after the page has been rendered when there is an error.

From my changeMyItem method (triggered by ng-blur) I've tried the expression syntax and it just becomes an empty div. I've also tried calling $scope.$apply in my success callback and it says $digest is already in progress and errors.

Without using a custom directive, how can I update itemError above with the related error?

Mike Cheel
  • 12,626
  • 10
  • 72
  • 101
  • As far as I see it changeMyItem is a function in your controller right? Then just set $scope.itemError if you found and error. Doesn't that work? – Tom Jul 14 '14 at 17:38
  • I'm trying to update just the individual item. – Mike Cheel Jul 14 '14 at 17:39
  • `ng-repeat` creates a new scope. There is a simple rule of thumb with data binding in angularJS which is explained in details there http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs . The short version is that there has to be a `.` where you put that `itemError`. – Alex C Jul 14 '14 at 17:40
  • I understand about the scope and protoypical inheritance. itemError is not part of my original dataset. It is a property I am trying to add to the child $scope but it isn't updating. – Mike Cheel Jul 14 '14 at 17:43
  • An easy way to do this would be building a separat array that contains the error message for every item id. Like `{{errorMessages[item.id]}}` and inside your controller in the changeMyItem function: `errormessages[item.id] = "Item error...";`. – Tom Jul 14 '14 at 17:47
  • `` is self closing tag BTW, does not accept children – charlietfl Jul 14 '14 at 17:47
  • I know I'm typing pseudo code. – Mike Cheel Jul 14 '14 at 17:49

3 Answers3

0

Well, I think the easiest way would be to ng-init a new object for each repeated table, and pass that to the changeMyItem function:

<table ng-repeat="item in items" ng-init="itemError = { message : '' }" >
    <tr>
        <td>
            <input ng-blur="changeMyItem($event, itemError)">{{item.Name}}</input>
        </td>
        <td>
            <div>{{itemError.message}}</div>
        </td>
    </tr>
</table>

Use an object with a property so that you pass it by reference to the function.

Then you can do:

$scope.changeMyItem = function(event, error) {
       //whatever
       error.message = "It didn't work!";
}
dave
  • 62,300
  • 5
  • 72
  • 93
0

You really should use a service:

<table ng-repeat="item in myForm.items track by $index">
  <tr>
      <td>
          <label>{{item.Title}}</label>
          <input ng-blur="myForm.changeMyItem($event, $index)" ng-model="item.Value">
      <td>
      <td>
          <div>{{item.Error}}</div>
      </td>
  </tr>
</table>

Then

app.factory('myForm', function(){
  var myform = {};
  myForm.items = [{ ... }];
  myForm.changeMyItem = function(event, index){

 };

  myForm.submit = function(){

  };

  myForm.setErrors = function(){

  };
  ...

  return myForm;

});
Alex C
  • 1,334
  • 2
  • 18
  • 41
0

Mike, If you are trying to set an error message for each individual input, this should do.

<table ng-repeat="item in items">
  <tr>
    <td>
       <input ng-blur="changeMyItem(item, $event)" ng-model="item.Name">
    <td>
    <td>
      <div>{{item.ErrorMessage}}</div>
    </td>
  </tr>
</table>

In you controller, you can have something similar to:

$scope.changeMyItem = function(item, $event) {
    if(!item.Name) {
       item.ErrorMessage = "This has error";
    }
}    
bentesha
  • 898
  • 9
  • 14
  • I was originally using the non-angular mindset (I've been working on other non angular projects until the past few days) and was trying was still thinking in the jquery mindset. What I ended up doing is extending my json objects when my call is done and extending them with the ErrorMessage property. Thne the data binding works as expected and all is good. So I basicially did what you are suggesting although I got it working before I saw this post. – Mike Cheel Jul 14 '14 at 19:13
  • Nice that it helped. Angular does most of the dirty works for you, including extending your objects and checking if a property exists without throwing an error – bentesha Jul 14 '14 at 20:21
  • I know I am just rusty. Been on a jquery based project for a long time so when switching back and forth sometimes one forgets the appropriate mindset. – Mike Cheel Jul 14 '14 at 20:59