A Guide to Uploading Multiple Rows Using AngularJS

I am facing a challenge with submitting a form that contains multiple table rows. While I have been able to successfully send the table data to the AngularJS controller, I am struggling to figure out how to forward that data to the apiController.

The form in question is a Purchase Order form that includes a table with Purchase Order Details. I have associated the submit button with both the Purchase Order and Purchase Order Detail submission 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();
$scope.POId = Math.floor(Math.random() * 1000000001);
$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);
        
        $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


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 Implemented changes as suggested


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);
}

Answer №1

When executing two functions, each sending an asynchronous request:

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

Consider the implications of sending both requests simultaneously without waiting for one to finish before starting the other.

A more efficient approach may involve combining all data into a single request for improved user experience, allowing the server to handle separate components if necessary. Alternatively, chaining Promises generated by $http can create a sequential process:

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

Another option is to utilize $q.all(promises).

Additionally, consider using a dedicated Angular Service to handle data posting for a cleaner and more scalable solution. Check out examples on the Angular Homepage.

Answer №2

I believe it may be more effective to combine the purchaseOrder and detail requests into one call instead of separate calls. Even though you can still organize the data as needed.

Running both functions simultaneously could lead to unexpected outcomes due to their asynchronous nature, potentially causing 'race conditions'.

Consider sending a single request and structuring how the information will be posted like this:

var data = {
    JobId: $scope.job.JobId,
    POId: $scope.POId,
    Order:{
        // Order details here
    },
    Detail:{
        // Detail specifics here
    }
}

You'll have to map the purchase order and detail data to a unified dto object in your api controller.

As a side note, I suggest utilizing a stronger unique identifier rather than just a random number for better security.

Answer №3

It appears that the issue lies within your controller. I recommend trying the following solution and providing more details about the problem. Is your API controller not being recognized by your main controller?

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

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The requested function is nowhere to be found within the confines of my Controller module

While working on a personal project, I encountered an issue where a function from another class in a separate Java file is not being found, even though it is defined in the respective class. EventView.js: displayEvent(event){ this.EventTitle = event. ...

JavaScript can intelligently extract and categorize an array of objects based on their properties

In essence, I aim to develop a versatile function "organize" that can transform the following data structure: [ { name: 'band1', type: 'concert', subtype: 'rock' }, { name: 'band2', type: 'concert' ...

What are the alternative methods to execute a React.js application without using react-scripts?

After creating my React.js app using the command below: npx create-react-app my-app I'm now looking to modify the package.json script section to run the app without react-scripts. How can I achieve this? "scripts": { "start&quo ...

Encountered a problem - "Parameter 'myCtrl' is not a valid function, received undefined"

Having trouble pinpointing my mistake. I tried following this guide with no success - How to find a reason AngularJS "Argument 'MyCtrl' is not a function, got undefined" Below is the content of my index.html file - <!DOCTYPE> & ...

Creating HTML displays using AngularJS templates

Here is my customized template: <div class="span12"> <ng:view></ng:view> </div> Now, looking at my view template: <h1>{{stuff.title}}</h1> {{stuff.content}} I have encountered an issue where the content appears as ...

Use Javascript or Jquery to dynamically change the background color of cells in HTML tables based on their numerical

I am working with a collection of HTML tables that contain numbers presented in a specific style: <table border="1"> <tr> <th>Day</th> <th>Time</th> <th>A</th> <th>B</th> &l ...

What is the purpose of creating redirects instead of just "processing" data?

Upon pressing the subscribe button, a form is submitted. Previously, I used axios. The POST request is sent to https://api.skymongoose.com/subscription. Why does it redirect to a blank page even though the URL points to https://api.skymongoose.com/subscri ...

Having difficulty importing an scss file into a react component

I'm trying to implement a spinner as a React component, but I'm facing difficulties applying the SCSS file to it. Here is a snippet of my loading.scss file: $color: #e14eca; $size: 12px; $time: 1; main { display: flex; justify-content: ce ...

I am unable to store a session variable using the GET method

Good day, I am seeking assistance with my code and have been searching for four hours without finding the error. I am working on an exchange where variables are stored in a session. The issue I am facing is that the variable $discount gets cleared every ti ...

Angular directive button failing to trigger ng-click event

Recently, I started working with Angular and ran into an issue while trying to set up a custom directive. The purpose of this directive is to display a button upon hovering over it, which, when clicked, should trigger a function within the directive. The b ...

Is there a way to quickly convert a deconstructed object into a specific type with just one

const { myFunc } = param[0].execute; Is there a way to convert myFunc to a string? This approach is ineffective const { myFunc } = param[0].execute as string; ...

sequence of events in which Node.js timer APIs are executed

I'm still a beginner when it comes to node.js and I'm trying to wrap my head around the concept of 'asynchronous' in relation to node js. Here is the code snippet that I'm currently working with: function foo() { setImmediate(f ...

Challenges in retrieving information from a two-dimensional JSON dataset

I am encountering an issue with a nested JSON structure. JSON: [{"id":"15", "rand_key":"", "landlord_name":"Shah", "property_req_1":{ "lead_req_id":"", "lead_id":"0", "category_id":"1", "region_id":"1", "area_location_id":"17", ...

Are there any disadvantages to keeping the selector of routed components in place?

The instructions in the Angular routing documentation - Add heroes functionality mention making some adjustments: Several changes need to be made: -Remove the selector (routed components do not need them). -Remove the <h1>. Is it beneficial to kee ...

The ng-click event is not triggering the Controller Function as expected

This is the Code for My View <div ng-controller="signupCtrl"> <ul class="list-group" > <li class="list-group-item"> <div class="form-group"> <input type="text" ng-model="signupCtrl.firstName"> ...

When using the ngFor directive in the <template>, the item is shown as [object Object] within the loop of items

When I interpolate a string variable in a repeated <li>, it displays correctly. However, when I place it within a <template><li>, it appears as [object Object]. What could be causing this issue? I have observed various versions of the < ...

Instructions for overlaying a text onto the select input field in DataTables

I am currently utilizing the DataTables select input feature to capture only the first three columns of data. However, I would like to enhance this by adding a text element above the select inputs within the DataTables interface. Is there a way to achieve ...

Encountered a snag while executing Powershell with Selenium: Error message - unable to interact with

Looking to update a textarea with a value? The script below triggers an error stating "element not interactable". This occurs because the textarea is set to "display:none". However, manually removing the "NONE" word allows the script to successfully set th ...

Using Ajax to update multiple text field rows with unique values

I have a question regarding utilizing Ajax to update the second text field based on the input from the first text field. I am looking to create multiple rows using a for loop, with each row having its own set of values. HTML <form style="text-align:c ...

Selenium: Perform a click action on a button enclosed within a "<div><a></a></div>" tag

I attempted to click on a button and encountered this structure: https://i.sstatic.net/GyGk3.jpg <div class="button-wrapper" id="button-verify-wrapper"> <a x-ng-click="verifySfdcConnection()" class="clearfix float-left button-green"> ...