문제

This application is for running a writing contest. Coodinators are assigning entries to judges for them to judge. I have three sets of data I retrieve from the server, a judge list, an entries list and an assignment list that ties the two together. There can be a variable number of input fields...if a judge has agreed to judge 4 entries, there will be 4 inputs...if 7, then 7. I have all of that working OK, but only insofar as the entry number can be input and the data updated.
Now I would like confirm that the entryID IS a valid ID by checking the list and also to show a field or two on the screen so the coordinator knows that they typed in the right entry.

The relevant section of the HTML

<div ng-app>
   <div id="assignment" ng-controller="AssignData" ng-init="JudgeID=107;CategorySelect='MS';PublishSelect='P'">
      <div ng-show="loaded">
         <form class="entryform ng-cloak" name="assignform" ng-submit="sendForm()">
            <p>Entry numbers assigned to this judge</p>
            <p ng-repeat="assign in (formassigns =(assigns | filter:AssignedJudge))">
               <input type="text" ng-model="assign.entryid" required/>
               {{entries.authorname}} {{entries.entrytitle}} 
            </p>
            <button type="submit">Save Assignments</button>
            <p>This will keep the assignments attached to this judge. 
               You will be able to send all of your assignments to all
               of your judges when you are finished.</p>
         </form>
      </div>
   </div>
</div>

The part that I haven't been able to figure out is how to make entries.authorname and entries.entrytitle show up when the user types in an entryid that is in entries.entryid.

assigns and entries are both arrays of records using JSON

assigns is JSON made up of assigns.id, assigns.judgeid, assigns.entryid.

entries is JSON made up of entries.entryid, entries.entrytitle, entries.authorname

When assigns arrives, entryid is empty. The form is used to fill in the entryid and when it is filled in, I'd like to be able to show next to it the title and authorname for that entry.

도움이 되었습니까?

해결책

NOTE: I've added some important information at the end of this answer. So please read to the end before you decide what you're going to do.

You're going to have to do something that does the look up.

Also a few other changes I'd add, mostly so you can actually validate the items in your repeat.

(There's a summary of what I did after the psuedo code below).

<div ng-app>
   <div id="assignment" ng-controller="AssignData" 
        ng-init="JudgeID=107;CategorySelect='MS';PublishSelect='P'">
      <div ng-show="loaded">
         <form class="entryform ng-cloak" name="assignform" ng-submit="sendForm()">
            <p>Entry numbers assigned to this judge</p>
            <p ng-repeat="assign in (formassigns =(assigns | filter:AssignedJudge))"
               ng-form="assignForm">
               <input type="text" ng-model="assign.entryid" 
                  ng-change="checkEntryId(assign, assignForm)"
                  name="entryid" required/>
               <span ng-show="assignForm.entryid.$error.required">required</span>
               <span ng-show="assignForm.$error.validEntry">
                   {{assignForm.$error.validEntry[0]}}</span>
               {{assign.entry.authorname}} {{assign.entry.entrytitle}} 
            </p>
            <button type="submit">Save Assignments</button>
            <p>This will keep the assignments attached to this judge. 
               You will be able to send all of your assignments to all
               of your judges when you are finished.</p>
         </form>
      </div>
   </div>
</div>

Then in your controller, you'd add a function like so (be sure to inject $http or a service you wrote to pull the values from the server):

$scope.checkEntryId = function(assign, form) {
   $http.get('/CheckEntry?id=' + assign.entryid,
      function(entry) {
         if(entry) {
           assign.entry = entry;
           form.$setValidity('validEntry', true);
         } else {
           form.$setValidity('validEntry', false, 'No entry found with that id');
         }
      }, function() {
           form.$setValidity('validEntry', true, 'An error occurred during the request');
           console.log('an error occurred');
      });
};

The basic idea above:

  • Use ng-form on your repeating elements to allow for validation of those dynamic parts.
  • Create a function that you can pass your item and your nested form to.
  • In that function, make your AJAX call to see if the entry is valid.
  • Check the validity based on the response, and call $setValidity on your nested form you passed to the function.
  • Use ng-show on a span (or something) in your nested form to show your validation messages.
  • Also, assign your checked entry to your repeated object for display purposes. (you could use a seperate array if you want, I suppose, but that would probably get unnecessarily complicated).

I hope that helps.

EDIT: Other thoughts

  1. You might want to wrap your call in a $timeout or some sort of throttling function to prevent the entry id check from spamming yoru server. This is an implementation detail that's totally up to you.
  2. If this is a check you do all over the place, you'll probably want to create a directive to do it. The idea would be very similar, but you'll do the check inside of a $parser on the ngModelController.
  3. The method I showed above will still actually update the model's entryid, even if it's invalid. This is usually not a big deal. If it is, you'll want to go with what I suggested in "other thought #2", which is a custom validation directive.

If you need more information about validation via custom directives I did a blog entry on that a while back

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top