4

I am trying to submit a form with multiple table rows. I have found examples online and have managed to send the table data to the AngularJS controller but I cannot figure out how to send that data to the apiController.

The form is a Purchase Order that has a table with the Purchase Order Details. I have chained the submit button with the both the Purchase Order and Purchase Order Detail submit functions.

<table class="table" style="">
    <tbody>
        <tr class="pointer no_selection" ng-repeat="newJobItem in rows">
            <td style="width:50px"><input style="width:20px" type="checkbox" class="form-control"></td>
            <td style="width:200px">{{newJobItem.JobItemName}}</td>
            <td style="width:480px">{{newJobItem.JobItemDescription}}</td>
            <td style="width:100px">{{newJobItem.JobItemMatSize}}</td>
            <td style="width:150px">{{newJobItem.JobItemQuantity}}</td>
            <td style="width:50px">{{newJobItem.JobItemUOM}}</td>
            <td style="width:150px">${{newJobItem.JobItemPrice | number : fractionSize}}</td>
            <td style="width:20px"><input type="button" value="X" class="btn btn-primary btn-sm" ng-click="removeRow(newJobItem.JobItemName)" /></td>
        </tr>

    </tbody>
</table>


<input style="margin-right:30px" id="btn-width" type="button" class="btn btn-default" ng-click="submitPurchaseOrder();submitPurchaseOrderDetail()" value="Submit"/>

Controller

   //Post Purchase Order
$scope.PODate = new Date(); //Todays Date
$scope.POId = Math.floor(Math.random() * 1000000001) //PurchaseOrder Id Generator
$scope.submitPurchaseOrder = function () {;
    var data = {
        JobId: $scope.job.JobId,
        POId : $scope.POId,
        PONumber: $scope.currentItem.PONumber,
        PODate: $scope.PODate,
        POAmount: $scope.currentItem.POAmount,
        POLastPrintDate: $scope.currentItem.POLastPrintDate,
        POEmail: $scope.POEmail,
        POPrint: $scope.currentItem.POPrint,
        POFaxNumber: $scope.POFaxNumber,
        PONotes: $scope.currentItem.PONotes,
        POCreatedBy: $scope.currentItem.POCreatedBy,
        PODeliveryDate: $scope.currentItem.PODeliveryDate,
        POShipVia: $scope.currentItem.POShipVia,
        POShowPrices: $scope.currentItem.POShowPrices,
        POCostCode: $scope.currentItem.POCostCode,
        POApprovedNumber: $scope.currentItem.POApprovedNumber,
        POBackorder: $scope.currentItem.POBackorder,
       }
    $http.post('/api/apiPurchaseOrder/PostNewPurchaseOrder', data).success(function (data, status, headers) {
        console.log(data);
        var tmpCurrentItem = angular.copy($scope.currentItem);
        $scope.purchaseOrderArray.push(tmpCurrentItem)
        angular.copy({}, $scope.currentItem);
        //hide modal window
        $scope.openNewPurchaseOrderModal.then(function (m) {
            m.modal('hide');
        });

    });
};
//Post Purchase Order Detail
$scope.newJobItem = {};
$scope.submitPurchaseOrderDetail = function () {
    var index = 0;
    $scope.rows.forEach(function (newJobItem) {
        console.log('rows #' + (index++) + ': ' + JSON.stringify(newJobItem));
    });
    var data = {
        POId: $scope.POId,
        PODItem: $scope.newJobItem.JobItemName,
        PODDescription: $scope.newJobItem.JobItemDescription,
        PODNotes: $scope.PODNotes,
        PODUOM: $scope.newJobItem.JobItemUOM,
        PODPrice: $scope.newJobItem.JobItemPrice,
        PODQuantity: $scope.newJobItem.JobItemQuantity,
        PODAmount: $scope.PODAmount,
        PODMatSize: $scope.newJobItem.JobItemMatSize,
        PODSection: $scope.PODSection,
        PODMultiplier: $scope.PODMultiplier,
        PODBackOrder: $scope.PODBackOrder
    }
    $http.post('/api/apiPurchaseOrderDetail/PostNewPurchaseOrderDetail', data).success(function (data, status, headers) {
        console.log(data); window.top.location.reload();

    });
};

Purchase Order Detail ApiController

 // POST api/<controller>

    public async Task<IHttpActionResult> PostnewPurchaseOrderDetail([FromBody]PurchaseOrderDetail newPurchaseOrderDetail)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        using (var context = new ApplicationDbContext())
        {
            context.PurchaseOrderDetails.Add(newPurchaseOrderDetail);
            await context.SaveChangesAsync();
            return CreatedAtRoute("PurchaseOrderDetailApi", new { newPurchaseOrderDetail.PODId }, newPurchaseOrderDetail);
        }
    }

Update Changed as suggested

 // POST api/<controller>
    public HttpResponseMessage PostNewPurchaseOrderDetail(int id, PurchaseOrderDetail newPurchaseOrderDetail)
    {
        ApplicationDbContext db = new ApplicationDbContext();
        if (!ModelState.IsValid)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }

        if (id != newPurchaseOrderDetail.PODId)
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }

        db.Entry(newPurchaseOrderDetail).State = EntityState.Modified;

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
        }

        return Request.CreateResponse(HttpStatusCode.OK);
    }

3 Answers 3

3
+50

You are executing two functions, each making an asyncronous request:

ng-click="submitPurchaseOrder();submitPurchaseOrderDetail()"

This doesn't feel right - both requests are sent in parallel and none is waiting for the other. Do you really mean it?

I would either package and send all data in a single request (also better experience for the user), then let the server deal with un-packaging. Or, if one request needs to wait for another, chain the Promises returned by $http:

$http.post(...)
     .then(function(){
         return $http.post(...);
     })
     .success(...)
     .fail(...);

or use $q.all(promises) instead.

EDIT.

Also a cleaner and more scalable approach is to use dedicated Angular Service to post your data, see e.g. example on Angular Homepage

Sign up to request clarification or add additional context in comments.

3 Comments

I wasn't sure how to do it, but using the Promises makes sense. But I still do not know how to send the PurchaseOrderDetail data to the apiController?
The only examples I found online that show how to submit multiple records are strongly typed projects.
@texas697 Your ajax request looks fine, you can try requestb.in to see how your request arrives, then test separately your PHP endpoint. Many examples out there, look for Angular/PHP.
3

I'm not sure about your approach, to me it would be better to join both requests, purchaseOrder and the detail into a single call, you can still separate the data as you may feel convenient.

calling both functions at the same time could have unexpected behaviors since both are running asynchronously you may find 'race conditions'.

try to send a single request and organize how you are going to post the information like

var data = {
    JobId: $scope.job.JobId, //common data between the order and the detail
    POId: $scope.POId,
    Order:{

        PONumber: $scope.currentItem.PONumber,
        PODate: $scope.PODate,
        POAmount: $scope.currentItem.POAmount,
        POLastPrintDate: $scope.currentItem.POLastPrintDate,
        POEmail: $scope.POEmail,
        POPrint: $scope.currentItem.POPrint,
        POFaxNumber: $scope.POFaxNumber,
        PONotes: $scope.currentItem.PONotes,
        POCreatedBy: $scope.currentItem.POCreatedBy,
        PODeliveryDate: $scope.currentItem.PODeliveryDate,
        POShipVia: $scope.currentItem.POShipVia,
        POShowPrices: $scope.currentItem.POShowPrices,
        POCostCode: $scope.currentItem.POCostCode,
        POApprovedNumber: $scope.currentItem.POApprovedNumber,
        POBackorder: $scope.currentItem.POBackorder,
    },
    Detail:{
        PODItem: $scope.newJobItem.JobItemName,
        PODDescription: $scope.newJobItem.JobItemDescription,
        PODNotes: $scope.PODNotes,
        PODUOM: $scope.newJobItem.JobItemUOM,
        PODPrice: $scope.newJobItem.JobItemPrice,
        PODQuantity: $scope.newJobItem.JobItemQuantity,
        PODAmount: $scope.PODAmount,
        PODMatSize: $scope.newJobItem.JobItemMatSize,
        PODSection: $scope.PODSection,
        PODMultiplier: $scope.PODMultiplier,
        PODBackOrder: $scope.PODBackOrder
    }

}

you'll need to map the purchase order and the detail to a single dto object in your api controller.

just as a sidenote, I'd recommend you to use a stronger unique identifier rather than using a random number.

Comments

0

I think the trouble is with you controller try using this and also can you please elaborate the trouble.Does your APIcontroller is never found by your controller ?

public class Oders : ApiController // in your controller class
{
 public HttpResponseMessage Post(PurchaseOrderDetails newOrder)
 {
 //your code
 }

}

6 Comments

ok, I modified the apiController to HttpResponseMessage instead of async. But i still need to set the Angular Controller to Send back the data and "rows". right now its not doing that. I do not know how to combine the 2
but I am curious why you suggested I changed the async to HttpResponse?
I am using the same thing where I am trying to add multiple entries and my controller makes a http request $http.post('/api/nameofcontroller/',this.newOrder).success...
are you using Angular in the front end? I need to get that setup first so i can see what happens in the controller
Yes I am using angular...but I thought you said earlier that you are getting data in your controller and the only problem was APIcontroller ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.