I have a page that contains a form, where part of it is dynamically generated based off of what SKU's are on an order.
<% for each i in ViewData.Model %>
<script type="text/javascript">
$(function () {
$('#return_<%=i.SKUN%>').change(function () {
if ($('#return_<%=i.SKUN%>').val() > $('#qty_<%=i.SKUN%>').val()) {
$('#Discrepancy').val("Yes");
} else {
$('#Discrepancy').val("");
}
});
});
</script>
<tr>
<td style="text-align: left"><%= i.SKUN%></td>
<td style="text-align: left; width: 360px"><%= i.DESCR%></td>
<td style="text-align: left">£<%= i.PRIC%></td>
<td style="text-align: left"><%= i.QUAN%></td>
<td style="text-align: left">£<%= i.EXTP%></td>
<td style="text-align: left"><input type="hidden" name="qty_<%=i.SKUN%>" id="qty_<%=i.SKUN%>" value="<%= i.QUAN%>"/><input type="text" name="return_<%=i.SKUN%>" id="return_<%=i.SKUN%>" style="width:50px;" class="required"/>
<% If i.FLAG3 = "T" Then
%> <img src="../../Content/images/icons/error.png" alt="This SKU is subject to a <%=Html.ViewData("RestockFee") %>% restocking fee" title="This SKU is subject to a <%=Html.ViewData("RestockFee") %>% restocking fee"/><%
End If%>
</td>
</tr>
<% Next%>
It's by no means perfect, but it gets the job done at the moment.
The part I'm struggling with is as return_<%=i.SKUN%> is a series of dynamically generated text boxes that change for each order, though they remain with the naming convention of return_<%=i.SKUN%>, how do I get the values for them in my controller that handles the form post?
EDIT: It's also important to note that none of these fields are required fields and that the number of text boxes varies per order.
Can't you change the naming convention to:
<input
type="text"
name="skuns[<%= index %>]"
id="return_<%= i.SKUN %>"
style="width:50px;"
class="required"
value="<%= i.SKUN %>"
/>
where index would be an incrementing variable from 0 to n. This way your controller action could look like this:
Public Function Result(skuns As String()) As ActionResult
And leave the default model binder do the job.
Related
I'm new to MVC Core and i'm having some struggles getting this right.
I've got a table filled with some basic values from my products, and what i want is to send a quantity value and an id of the product to my action method. The problem i'm having is that i'm able to send my product.ID to the action method, but i can't seem to get my input value. I tried using a button instead of my element and when i used that i managed to get the input but not the product.ID.
#model List<Product>
<div id="productList">
<form>
<table>
#foreach (var product in Model)
{
<tr>
<td>#product.Name</td>
<td>#product.Price</td>
<td><input type="text" name="quantity" /></td>
<td>
<a
asp-action="AddProductToCart"
asp-route-id="#product.ID"
data-ajax="true"
data-ajax-method="GET"
data-ajax-mode="replace"
data-ajax-update="#cartinfo">Add to basket</a>
</td>
</tr>
}
</table>
</form>
</div>
<div id="cartinfo">
</div>
My action methods parameters looks like this:
public IActionResult AddProductToCart(int id, int quantity)
I'm sure i'm missing some basic knowledge about how forms work so i'd really appreciate getting some help here. I've been trying to google this but i'm struggling with that as well. Thanks a lot
You can use javascript instead.
#model List<Product>
<div id="productList">
<form>
<table>
#foreach (var product in Model)
{
<tr>
<td style="visibility:hidden" class="pID">#product.ID</td>
<td>#product.Name</td>
<td>#product.Price</td>
<td><input type="text" name="quantity" class="qty"/></td>
<td>
<button class="btnAdd" >Add to basket</button>
</td>
</tr>
}
</table>
</form>
</div>
<div id="cartinfo">
</div>
java script
<script type="text/javascript">
$(document).ready(function () {
$('.btnAdd').click(function () {
var PID= $(this).closest("tr").find(".pID").text();
var Pqty= $(this).closest("tr").find(".qty").text();
AddtoCart(PID, Pqty);
});
});
function AddtoCart(pid,qty) {
$.ajax({
url: "#Url.Action("AddProductToCart", "Your Controller")",
type: 'GET',
data: { id: pid, quantity: qty},
datatype: 'json',
success: function (data) {
$('#cartinfo').html(data);
}
});
}
</script>
Hope this will help you!
Oh man, now i know what developers mean when they say that their code from 1 year ago is trash. Not sure if i should feel embarrassed or proud, haha.
My solution now would've probably been to post using JS. Also i wouldn't have placed my "asp-route-id="#product.ID" on an element, i could've just put it as a hidden input and posted it. Oh and that data-ajax-mode stuff confused me more than it helped, remove that for sure.
Note to self: Keep improving. :-)
You could try to put data-ajax attribute in the <form> ,and make the following changes in your view and the parameter in the action
<div id="productList">
<table>
#foreach (var product in Model)
{
<tr>
<form data-ajax="true"
data-ajax-url="/Your controllerName/AddProductToCart"
data-ajax-method="Post"
data-ajax-mode="replace"
data-ajax-update="#cartinfo">
<td>#product.Name</td>
<td>#product.Price</td>
<td>
<input type="text" asp-for="#product.quantity"/>
<input asp-for="#product.Id" hidden />
</td>
<td>
<input type="submit" value="Add to basket"/>
</td>
</form>
</tr>
}
</table>
Change the parameters to Model object , note that the parameter name must be consistent with the name of the data passed from the client side
[HttpPost]
public IActionResult AddProductToCart( Product product)
{
//the stuff you want
}
I need help creating an 'edit' action that selects a specific model from a list of models, and in that table, edits the model. A quick-edit of sorts.
<tbody>
{{#each}}
<tr class="people-list">
<td>
<input type="checkbox" class="toggle">
<label class="category-text">{{#linkTo 'category' this}}{{Name}}{{/linkTo}} </label>
<img class="table-img" src="images/x.png">
<img class="table-img" {{action 'edit'}} src="images/pencil-grey.png">
</td>
</tr>
{{/each}}
</tbody>
By clicking {{action 'edit'}}, {{Name}} becomes and editable input. This is all done without leaving the '/categories' url.
Thanks guys :D
<tbody>
{{#each}}
<tr class="people-list">
<td>
<input type="checkbox" class="toggle">
{{#if isEdit}}
{{input type="text" valueBinding="Name" name="Name"}}
{{else}}
<label class="category-text">{{#linkTo 'category' this}}{{Name}}{{/linkTo}}</label>
{{/if}}
<img class="table-img" src="images/x.png">
<img class="table-img" {{action 'edit'}} src="images/pencil-grey.png">
</td>
</tr>
{{/each}}
</tbody>
And then on the controller:
actions: {
edit:function(){
this.set('isEdit', true);
}
}
Hello im back with another tedious question!
Trying to get my table to paginate. There are 12 users in the table. Here is my controller function
def listDuplicates(params) {
def result = User.getAllWithDuplicateIDs()
def totalDupCount = result.size()
/*sout for troubleshooting */
System.out.println("Duplicate:" + result.ID + " " + result.username)
params.max = Math.min(params.max ? params.int('max') : 10, 100)
return [resultList: result, totalDupCount: totalDupCount, params:params ]
}
Here is my view
<div>
<fieldset class="warningFieldSet">
<h1 style="color: red" align="center">
<g:message code="Duplicate IDs" />
</h1>
<p style="color: red; margin-left: 20px;">Duplicate IDs Found!</p>
<table>
<thead>
<tr>
<g:sortableColumn property="Username" title="Username" />
<g:sortableColumn property="ID" title="ID" />
<g:sortableColumn property="Status" title="Status" />
</tr>
</thead>
<tbody>
<g:each in="${resultList}" status="i" var="resultDuplicate">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<td>
${resultDuplicate.username}
</td>
<td style="color: red; font-weight: bold">
${resultDuplicate.id}
</td>
<td>
${resultDuplicate.accountStatus }
</tr>
</g:each>
</tbody>
<tfoot>
<g:if test="${totalDupCount >10 }">
<div class="paginateButtons">
<g:paginate action= "listDuplicates" total="${totalDupCount}" />
</div>
</g:if>
</tfoot>
</table>
</fieldset>
</div>
Domain function for finding the duplicate IDs
static List<User> getAllWithDuplicateIDs() {
findAll("FROM User WHERE id IN (SELECT id FROM User group by id having count(*) > 1) AND id != '' ", [])
}
The buttons show up. And in the URL the offset and max is displayed. The table just puts all 12 displayed instead of 10 on one page and 2 on the other. 2 Page numbers show up so It knows that it is only suppose to display only 10 per page. It just isn't doing it in the table itself. Im assuming its some kind of issue with passing params and such.
Any Suggestions/Opinions/Help are/is greatly appreciated!
Grails pagination is based on two parameters: max and offset. max determines the page size, and offset determines where the current page starts. The controller receives these parameters and generally passes them to a database query. The list method added to domain objects by grails handles these parameters, and the finder methods take a queryParams. The usual pattern is to pass the params object directly to list or as the queryParams parameter to the finders. This returns a result set starting at the given offset, with one page length.
In your example, you're calling getAllWithDuplicateIDs without making use of these parameters. Update your query to take them, like this:
static List<User> getAllWithDuplicateIDs(params) {
findAll("FROM User WHERE id IN (SELECT id FROM User group by id having count(*) > 1) AND id != '' ", [], params)
}
Alternatively, page it in memory with something like
results = results.drop(params.offset).take(params.max)
Paging directly in the query is preferable, since it will perform better handle cases where the entire list doesn't fit in memory.
Provide max and offset function params this:
def result = User.getAllWithDuplicateIDs([max:params.max, offset:params.offset])
And use them in in query to database.
Or check the answer how to get results from list with max and offset in answer here
Look at this example .
Domain class ..
class Job {
static belongsTo = [company:Company]
String jobtitle
String jobdescription
String jobskills
String joblocation
String experience
String jobtype
String salary
}
Controller Code..
def uijobs () {
[res:Job.list(params),jobcount:Job.count()]
}
and view is here.
<div class="container" id="main">
<div class="row">
<g:each in="${res}">
<div class="col-sm-4">
<div class="panel panel-warning">
<div class="panel-heading">
<h4 class="panel-title"><g:link action="infopagejob" controller="Job" id="${it.id}">${it.jobtitle}</g:link></h4>
</div>
<div class="panel-body">
<table class="table">
<tr class="info" >
<td > Job Location</td>
<td >${it.joblocation}</td>
</tr>
<tr class="info">
<td>Description</td>
<td>${it.jobdescription}</td>
</tr>
</table>
</div>
</div>
</div>
</g:each>
</div>
<g:paginate next="Forward" prev="Back" maxsteps="10" controller="Job" action="uijobs" total="${jobcount}" params="${params}"/>
</div></div>
1.I want to dynamically generate div containing textbox with unique id on click of button
<input id="<%:rid %>" type="button" value="reply"/>
2.I also want to use jquery ajax mathod to carry the textbox data to ashx file .
Can anyone help me
code
var lineItemCount = 0;
$(document).ready(function () {
$(".commentbox input[type='button']").click(function () {
var id = $(this).attr("id");
alert(id);
var cid = id.substring(5);
var containerid = "container" + cid;
alert(containerid);
//Increase the lineitemcount
lineItemCount++;
//Add a new lineitem to the container, pass the lineItemCount to makesure
getLineItem()
// can generate a unique lineItem with unique Textbox ids
$(containerid).append(getLineItem(lineItemCount));
});
});
//Create a new DIV with Textboxes
function getLineItem(number) {
var div = document.createElement('div');
//Give the div a unique id
div.setAttribute('id', 'lineitem_' + number);
//pass unique values to the getTextbox() function
var t1 = getTextbox('txt_' + number + '_1');
div.appendChild(t1);
return div;
}
//Create a textbox, make sure the id passed to this function is unique...
function getTextbox(id) {
var textbox = document.createElement('input');
textbox.setAttribute('id', id);
textbox.setAttribute('name', id);
return textbox;
}
iteration through model in aspx page
<%var i=1;%>
<%foreach (var commentitem in item.commentsModelList)
{
<table border="0" class="commentbox">
<tr>
<%var rid = "reply" + i;%>
<div id="<%:containerid %>">
<td> <input id="<%:rid %>" type="button" value="reply"/>
</div>
</td>
</tr>
</table>
<% i++;}%>
I changed your markup little bit to get the corresponding id of items on my click events
HTML
<table border="0" class="commentbox">
<tr>
<td>Some Item text
</td>
</tr>
<tr>
<td>
<div id="container-1" ></div>
<input type="button" class='btnReply' id="reply-1" value="Reply" />
</td>
</tr>
</table>
And the Script
$(function(){
$(".commentbox .btnReply").click(function(){
$(this).hide();
var id=$(this).attr("id").split("-")[1]
var strDiv="<input type='text' class='txtCmnt' id='txtReply-"+id+"' /> <input type='button' class='btnSave' value='Save' id='btnSave-"+id+"' /> ";
$("#container-"+id).html(strDiv);
});
$(".commentbox").on("click",".btnSave",function(){
var itemId=$(this).attr("id").split("-")[1]
var txt=$(this).parent().find(".txtCmnt").val();
$.post("/echo/json/", {reply: txt, id: itemId},function(data){
alert(data);
//do whatever with the response
})
});
});
Here is the jsfiddle example : http://jsfiddle.net/UGMkq/30/
You need to change the post target url to your relevant page which handles the ajax response.
EDIT : As per the comment about handing Multiple Divs
As long as you have the container div ids unique, it will work, I just changed the markup to include more than one item.
<table border="0" class="commentbox">
<tr>
<td>Some Item text<br/>
<div id="container-1" ></div>
<input type="button" class='btnReply' id="reply-1" value="Reply" />
</td>
</tr>
<tr>
<td>Some Another Content here <br/>
<div id="container-2" ></div>
<input type="button" class='btnReply' id="reply-2" value="Reply" />
</td>
</tr>
</table>
Here is the sample :http://jsfiddle.net/UGMkq/44/
For the above output to be rendered, you probably want to write your razor syntax like this
<table border="0" class="commentbox">
#foreach (var commentitem in item.commentsModelList)
{
<tr>
<td>Some Another Content here<br/>
<div id="container-#(commentitem.Id)" ></div>
<input type="button" class='btnReply' id="reply-#(commentitem.Id)" value="Reply" />
</td>
</tr>
}
</table>
Instead of creating a new table for each item, I created a new row in existing table.
I am writing a small application in Classic ASP. I have a page which has a form, which posts to a second page. Included with the form's POST, are file uploads, hence the need for a POST method.
The second page though is NOT seeing ANY of the fields being sent by the first page. Calling either Request("param") or Request.Form("param") both just return empty string.
If i switch the method on my form from POST to GET (with NO other changes), then the values are properly picked up by the receiving page, of course then I cannot do the file uploads, which are a crucial part of this application.
In GET mode, the parameters are all put on the url as expected. In POST mode, I fired up FireBug, and examined the POST data of my request. The originating form IS sending all the values in the request (they show up in FireBug as expected), so the problem seems to be on the receiving page's end.
The form is being submitted via code, called from the button with the onclick="javascript:saveMinutes();"
My form and the saveMinutes() function are declared as follows:
<form id="frmMinutes" enctype="multipart/form-data" method="post" action="saveminutes.asp">
<table id="tblMinutes" style="width: 100%;">
<tr>
<td>
<select id="selYear" name="year" size="13" onclick="javascript:setDatePickerRange(); checkForMinutes();">
<%For lc = Year(Now) To getMinutesFirstYear() Step - 1%>
<option value="<%=lc%>" <%If lc = Year(Now) Then%>selected="selected"<%End If%>><%=lc%></option>
<%Next%>
</select>
</td>
<td>
<select id="selMonth" name="month" size="13" onclick="javascript:setDatePickerRange(); checkForMinutes();">
<%For lc = 1 To 12%>
<option value="<%=lc%>" <%If lc = Month(Now) Then%>selected="selected"<%End If%>"><%=MonthName(lc)%></option>
<%Next%>
</select>
</td>
<td style="width: 100%; padding-left: 20px;">
<table id="enterMinutes" style="width: 100%">
<tr>
<th>Topic:</th>
<td><input id="topic" name="topic" type="text" maxlength="100" field="topic" /></td>
</tr>
<tr>
<th>Presenter:</th>
<td><input id="presenter" name="presenter" type="text" maxlength="100" field="presenter" /></td>
</tr>
<tr>
<th>Date:</th>
<td><input id="mtgdate" name="mtgdate" type="text" maxlength="10" class="datepick" field="mtgdate" readonly="readonly" /></td>
</tr>
<tr>
<th style="vertical-align: top;">Files:</th>
<td style="text-align: left;">
<input id="file0" name="file0" type="file" size="35" /><span class="redEmphasis" style="margin: 0px 10px 0px 10px;">(.doc or .docx)</span><input type="button" value="+" onclick="javascript:addFileUpload();" />
</td>
</tr>
<tr>
<th style="vertical-align: top;"></th>
<td style="text-align: left; padding: 10px 0px 10px 0px;">
<input type="button" style="width: 100%" value="update minutes" onclick="javascript:saveMinutes();" />
</td>
</tr>
</table>
<span id="warnexist" class="redEmphasis" style="display: none;">The selected month already has associated minutes (). doc files take precedence over docx.</span>
</td>
</tr>
</table>
</form>
saveMinutes():
function saveMinutes() {
if($('form#frmMinutes input[type=text]').filter(function () { return $(this).val() == '' }).length > 0) {
alert('Please enter all fields.');
return;
}
if ($('form#frmMinutes input#file0').filter(function () { return !$(this).val().match(/.*\.docx?$/i) }).length > 0) {
alert('First file must be doc or docx.');
return;
}
$('form#frmMinutes input[type=file]').filter(function () { return $(this).val() == '' }).next().remove();
$('form#frmMinutes input[type=file]').filter(function () { return $(this).val() == '' }).remove();
removeDupeFiles();
// reindex file inputs after removing emptys/dupes
var fs = $('form#frmMinutes input[type=file]:gt(0)');
for (lc = 1; lc <= fs.length; lc++) {
var fid = 'file' + new String(lc);
$(fs[lc-1]).attr('id', fid).attr('name', fid);
}
$('form#frmMinutes')[0].submit();
}
When your from is encoded as multipart, you can't get the POST values as plain old parameters. They are just additional parts of the multipart form.
To retrieve the uploaded files in ASP, you typically have to loop through the parts and check each one to see if it is a file (and then save it if it is). To get field values, you have to add to that loop to check each part to see if it has the name of one of your field values, and then retrieve the value. This is a pain to do in pure ASP code, so many people use some type of file upload component, in which case the retrieval of field values will depend on the component.
But the basic message is: whatever parsing of the form you're doing to retrieve the files, you have to do the same thing to retrieve the field values.