sending array of ints from js to the controller - javascript

Inside view I have list of images with corresponding checkboxes. I want to check
image or images and store image id's to int array. This int array should be sent to the
controller for further process.
I'm already spend too much time on this and I'm getting int[] data null at controller
Question is:
Why I'm getting null at controller?
SOLVED!
In my _Layout jquery scripts bundle call was at the end of the document, when I was move to the top everything works.
View
<div id="newsImages">
<img width="50" height="50" alt="" src="/imageOne.jpg">
<input type="checkbox" class="imgCheckbox" id="4">
<img width="50" height="50" alt="" src="/imageTwo.jpg">
<input type="checkbox" class="imgCheckbox" id="5">
<input type="button" value="Delete" name="deleteImgBtn" id="deleteImgBtn" class="deleteImagesBtn">
</div>
JS
var imgList = [];
$(document).on("click", "#deleteImgBtn", function (e) {
e.preventDefault();
$('.imgCheckbox:checked').each(function () {
var id = $(this).attr('id');
//add image id to the array of ints
imgList.push(id);
});
jQuery.ajaxSettings.traditional = true;
var options = {
url: '/news/deleteimages',
type: 'POST',
data: { data: imgList },
traditional: true
};
$.ajax(options).done(function (data) {
var $target = $('#newsImages');
$target.html(data);
});
//reset array of int to prevent browser to send duplicated
//img id to the controller on second attempt after ajax request is completed
imgList.length = 0;
//prevent browser from any default actions
return false;
});
CONTROLLER
public ActionResult DeleteImages(int[] data)
{
...
}

You can seralize your array and send it via ajax.
Serializing to JSON in jQuery
and read the seriazlized array, parse it..check every thing and go

Use JSON.stringify.
var myarr = [];
myarr[0] = 'as';
myarr[1] = 'we';
console.log ( JSON.stringify( myarr ) );
Output is:
["as","we"]
On your PHP side, use json_decode:
print_r( json_decode('["as","we"]') );
will output:
Array ( [0] => as [1] => we )

Related

Ajax search doesn't work the second time (ASP.NET MVC)

I have a problem changing items after searching.
I looked at similar threads but found no solution there :(
It looks like the first time the page loads well - the first time the entire Index.cshtml page is loaded which contains a collection of books in the selected category.
There is a search engine on the page - after searching for "manual" - ajax correctly replaces elements with those containing "manual" in the name.
Then when I enter something into the search engine a second time (for example "exercises") - the content of the page does not change any more.
I tried to debug and I see that new items are correctly downloaded from the database - the condition "if (Request.IsAjaxRequest ())" is true and the items are passed to partial view - there the "foreach" loop goes through them. Unfortunately, after _Partial, nothing happens.
I can't find a mistake - the strangest thing is that the first ajax call works fine - only the second (and subsequent) bad.
CatalogController.cs
public ActionResult Index(string categoryName = null, string searchQuery = null)
{
if (categoryName == null)
categoryName = (db.Categories.Find(1)).Name;
var category = db.Categories.Include("Books").Where(x => x.Name.ToLower() == categoryName).Single();
var books = category.Books.Where(x => (searchQuery == null || x.Title.ToLower().Contains(searchQuery.ToLower()) || x.SubTitle.ToLower().Contains(searchQuery.ToLower()) || x.Level.ToLower().Contains(searchQuery.ToLower())) && !x.Inaccessible);
if (Request.IsAjaxRequest())
return PartialView("_PartialBooksList", books);
else
return View(books);
}
Index.cshtml
<form class="o-search-form" id="search-form" method="get" data-ajax="true" data-ajax-target="#booksList">
<input class="o-search-input" id="search-filter" type="search" name="searchQuery" data-autocomplete-source="#Url.Action("SearchTips")" placeholder="Search" />
<input class="o-search-submit" type="submit" value="" />
</form>
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
#section Scripts
{
<script src="~/Scripts/jquery-3.5.0.js"></script>
<script src="~/Scripts/jquery-ui-1.12.1.js"></script>
<script>
$(function () {
var setupAutoComplete = function () {
var $input = $(this);
var options =
{
source: $input.attr("data-autocomplete-source"),
select: function (event, ui) {
$input = $(this);
$input.val(ui.item.label);
var $form = $input.parents("form:first");
$form.submit();
}
};
$input.autocomplete(options);
};
var ajaxSubmit = function () {
var $form = $(this);
var settings = {
data: $(this).serialize(),
url: $(this).attr("action"),
type: $(this).attr("method")
};
$.ajax(settings).done(function (result) {
var $targetElement = $($form.data("ajax-target"));
var $newContent = $(result);
$($targetElement).replaceWith($newContent);
$newContent.effect("slide");
});
return false;
};
$("#search-filter").each(setupAutoComplete);
$("#search-form").submit(ajaxSubmit);
});
</script>
}
_PartialBooksList
#model IEnumerable<ImpressDev.Models.Book>
#using ImpressDev.Infrastructure
<div class="row">
#foreach (var book in Model)
{
<div class="col-12 col-xl-4">
<a class="o-shop-link" href="#Url.Action("Details", "Catalog", new { bookId = book.BookId })">
<div class="o-shop-item">
<img class="o-shop-img" src="#Url.BookPhotoSourcePath(book.PhotoSource)" />
<div class="o-shop-text">
<h2>#book.Title</h2>
<h6>#book.SubTitle - #book.Level - <b>#book.Price zł.</b></h6>
+ Add to cart
</div>
</div>
</a>
</div>
}
</div>
Please help
I am not sure if this is the case, but try to change this code:
$($targetElement).replaceWith($newContent);
To this:
$($targetElement).html($newContent);
I think the problem is the div element with id="booksList" is replaced after first search. So you don't have this element in the second search.
I looked through the code step by step and found a solution to my problem.
In the first search, replace id="booksList"
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
partial view in which there was only without id = booksLists.
In the next search there was no ID in this place and there was nothing to replace.

How to return and access an object from a Javascript on a button post submitted?

I am working on a Javascript that aims to return then manipulate an object from a clicked button. I am now stuck how can i get its object then process it on a post method. On my button I have this:
<button type="submit" name="submit" form="form-add" id="export-btn" class="btn btn-small" style="border-radius: 0;"><i class="fas fa-save"></i><span class="button-save"></span>Save</button>
and i have this javascript method:
<script type="text/javascript">
var $TABLE = $('#table');
var $BTN = $('#export-btn');
var $EXPORT = $('#export');
...
// A few jQuery helpers for exporting only
jQuery.fn.pop = [].pop;
jQuery.fn.shift = [].shift;
$BTN.click(function () {
var $rows = $TABLE.find('tr:not(:hidden)');
var headers = [];
var data = [];
// Get the headers (add special header logic here)
$($rows.shift()).find('th:not(:empty)').each(function () {
headers.push($(this).text().toLowerCase());
});
// Turn all existing rows into a loopable array
$rows.each(function () {
var $td = $(this).find('td');
var h = {};
// Use the headers from earlier to name our hash keys
headers.forEach(function (header, i) {
h[header] = $td.eq(i).text();
});
data.push(h);
});
// Output the result
$EXPORT.text(JSON.stringify(data));
return data;
});
</script>
and on top of my page I have this:
if(isset($_POST['submit'])){
echo "Test";
// Process here the object
}
but How can i access those data, since $EXPORT.text(JSON.stringify(data)); output a JSON, that looks like this [{"id":"1","Val":"Sample","data":"Sample Date"}] on my paragraph tag.
You can't post data from paragraph.
Create hidden input in the form and assign the data to it.
$(this).append($("<input />", { name : "foo", value : data, type : "hidden" }))

display loading image with jquery/ajax

I am trying to display a spinning image while ajax call is being completed. I am using the following jsp and jquery code yet it is not working.
Any help will be appreciated
jsp:
<div class="tab-content" id="rdfTabs">
<div id="data">
<p>Please enter dataset URL or absolute file location (e.g: c:\data\dbpedia.rdf)</p>
<table width="100%">
<tr>
<td colspan="2"><input name="txtDataSource" id="txtDataSource" type="text" class="textbox"/>
<input type="button" value="Analyse File"
name="btnAnalyseFile" id="btnAnalyseFile" class="btn-blue" /></td>
</tr>
</table>
**<div id="loadingImage" style="display:none">
<img src="http://preloaders.net/preloaders/287/Filling%20broken%20ring.gif">
</div>**
<p id="presult">
</div>
and here is the jquery code
$(document).ready(function()
{
$("#presult").hide();
$("#btnAnalyseFile").click(
function(e)
{
**$("#loadingImage").show();**
$.ajax({
url : 'CreatePatternServlet',
type : 'POST',
dataType : 'json',
data : $("#formCreatePattern").serialize(),
success : function(data)
{
if(data.analyseResult==true){
var predicates = {};
var objectList = {};
var ddlSubject = $('#ddlSubject');
var ddlPredicate = $('#ddlPredicate');
var ddlObject = $('#ddlObject');
var ddlClass = $('#ddlClass');
$.each(data.Subjects, function(key, value)
{
ddlSubject.append($('<option></option>')
.val(value).html(key));
});
$.each(data.Classes, function(key, value)
{
ddlClass.append($('<option></option>')
.val(value).html(key));
});
$.each(data.Predicates, function(key, value)
{
ddlPredicate.append($('<option></option>')
.val(value).html(key));
});
$.each(data.Objects, function(key, value)
{
ddlObject.append($('<option></option>')
.val(value).html(key));
});
$('#ddlSubject').filterByText(
$('#txtSearchSubject'));
$('#ddlPredicate').filterByText(
$('#txtSearchPredicate'));
$('#ddlObject').filterByText(
$('#txtSearchObject'));
$('#ddlClass').filterByText(
$('#txtSearchClass'));
$("#presult").html("Data uploaded successfully");
$("#presult").css("color","green");
$("#presult").fadeIn(500);
}
else{
$("#presult").html("Upload failed, please check file path or URL. Server returned error: "+data.result);
$("#presult").css("color","red");
$("#presult").fadeIn(500);
}
}
});
**$('#loadingImage').hide();**
return false;
});
});
Problem is that your ajax function is asynchronous, so you are showing the loader, firing the ajax and inmediately hiding the loader, without waiting for the request to end.
Easy fix is putting the $('#loadingImage').hide(); inside the success function, but would be better to add a done function in case it fails
$("#btnAnalyseFile").click(function() etc...
shoudn't be
$("#btnAnalyseFile").on("click", function() { etc...
?

HTML.Action Loop results in wrong model on page (variable scope pollution?)

I have a view (cshtml) that has a tab strip on it. The contents of each tab is of course different. The individual tabs have the correct data/information on them. There is some javascript that is intended to fire when a selection is made from the control on the individual tab. As it stands right now the first tab rendered the javascript fires. All other tabs do not fire. Further on the tab that does fire (first one) it obtains the correct value but then when trying to find the matching item in the model it doesn't find a match. Debugging shows that only the data for the last tab is available in the model. Well that explains why no match but begs the question of where did the data the first page was populated with go?
I have snipped the code for brevity. If, in my ignorance I left something out just say so and I'll post whatever is needed.
So to start here is the parent cshtml:
foreach (var extbrd in Model.ExternalBoards)
{
tabstrip.Add()
.Text(extbrd.ExtForumName)
.ImageUrl("~/.../ForumTabIcon.png")
.Content(#<text>
<div>
#Html.Action("ActionName", "Controller", new { id = extbrd.BoardId });
</div>
</text>);
}
Well as you can see above as we loop we call an action in the controller for each tab. Here is that action:
public ActionResult ActionName(int extforumid)
{
//get url for selected forum (tab) and pull feed
ExternalForums ExtFrm = _forumService.GetExternalForumById(extforumid);
reader.Url = ExtFrm.ForumUrl;
return View(reader.GetFeed());
}
That's actually it. As above I can post the reader code but I don't think it is the source of the trouble.
Well this action of course has a view and this is where I think things get wacky:
#model ExternalThreadsModel
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model.RssThreads))
</script>
<script type="text/javascript">
$(function() {
$("##Html.FieldIdFor(model => model.ExtForumIds)").click(function () {
var selectedItem = $(this).val();
var matchingObj = getObjects(model, 'ThreadValue', selectedItem);
if(matchingObj > 0)
{
var $iframe = $('#ForumFrame');
if ( $iframe.length ) {
$iframe.attr('src', matchingObj[0].Link);
}
var $prevfram = $('#ForumPreview');
if ( $prevfram.length ) {
$prevfram.val(matchingObj[0].Description);
}
}
});
});
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
</script>
<div>
<table>
<tr>
<td>
#Html.DropDownListFor(model => model.ExtForumIds, Model.SelectThreads, new {style = "...", #size = 30})
</td>
<td style="width:25px;"> </td>
<td>
#{ Html.Telerik().TabStrip()
.Name("ForumView")
.Items(tabstrip =>
{
tabstrip.Add()
.Text("Preview")
.Content(#<text>
<div>
<textarea style="background-color:#979797; text-decoration: none;" id="ForumPreview" name="ForumPreview" rows="26" cols="200" readonly></textarea>
</div>
</text>);
tabstrip.Add()
.Text("Interactive")
.Content(#<text>
<div>
<iframe id="ForumFrame" name="ForumFrame" src="" style="width:800px;height:350px;"></iframe>
</div>
</text>);
})
.SelectedIndex(0)
.Render();
}
</td>
</tr>
</table>
</div>
So as I mentioned each tab does have the correct data / information on it. The problem comes when a user selects an item from the drop down list.
The click handler only fires on the first tab. It doesn't fire for any other tabs???
Further on the first tab the click handler does fire and it pulls the correct selectedItem but when it runs through the helper function getobjects it doesn't find a match.
When I break and examine "model" as it is being passed into getObjects it only contains data for the last tab...so yeah nothing is going to be matched.
What is even stranger for me to understand is the line:
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model.RssThreads))
</script>
In HTML it does render a json object with ALL the data from ALL the tabs...so...somewhere I must be running into variable scope pollution????
Your support and assistance is..as always..greatly appreciated.

How do I do a list of items in Jquery and get it on server side?

I'm trying to make a list of items (telephones and dependents for a customer), for example, the user could include some number phones and remove others (maybe edit them if it is possible), like a list inside the record of customer.
I'd like to know how can I do it on client side and get the list in server side ?
Is there a jquery plugin or a best pratice to do it?
P.S.: I'm using ASP.Net MVC 2.
Serialise the data into a format like JSON and then send it to the server as a string.
When I had to learn it, these posts were extremely useful.
http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/
http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/
You can serialise a javascript array into a string that ASP.Net can deserialise.
There is a standard called JSON which is good, as it adds nearly no noise on the actual data (like xml does, incrementing a LOT the amount of data to transfer).
You can then use the $.ajax jquery method to send this data to a WebMethod you created (see links) and get an understandable response back.
EDIT:
If you were already inside this stuff, you can simply use the JSON.stringify() method, passing the object/array to serialise in it.
I keep this example around to get me started, just put the proper stuff in the proper files and edit it to match what you are doing:
/* in this case I am using */
available at: http://www.json.org/js.html
function jsonObject()
{
};
var phoneListObject = new jsonObject();
function SaveJsonObject()
{
phoneListObject.Control = new jsonObject();
phoneListObject.Control.CustomerId = $("#CustomerId").val();
phoneListObject.Control.CustomerName = $("#CustomerName").val();
phoneListObject.ListBody.PhonesBlock = new jsonObject();
phoneListObject.ListBody.PhonesBlock.Phone = new Array();
$('#PhonesBlock .Phone').each(function(myindex)
{
phoneListObject.ListBody.PhonesBlock.Phone[myindex].PhoneNumber = $(".PhoneNumber input", this).val();
phoneListObject.ListBody.PhonesBlock.Phone[myindex].PhoneName = $(".PhoneName input", this).val();
});
};
$(function()
{
function SaveCurrentList()
{
SaveJsonObject();
var currentSet = phoneListObject;
var formData = { FormData: currentSet };
phoneListJSON = JSON.stringify(formData);
var FormData = "{ FormData:" + JSON.stringify(phoneListJSON) + "}";
SavePhoneListData(FormData);
};
function SavePhoneListData(phonesData)
{
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
data: phonesData,
dataFilter: function(data)
{
var msg;
if ((typeof (JSON) !== 'undefined') &&
(typeof (JSON.parse) === 'function'))
msg = JSON.parse(data);
else
msg = eval('(' + data + ')');
if (msg.hasOwnProperty('d'))
return msg.d;
else
return msg;
},
url: "../../WebServices/ManagePhones.asmx/SaveJson",
success: function(msg)
{
SaveSuccess(msg);
},
complete: function(xhr, textresponse)
{
var err = eval("(" + xhr.responseText + ")");
},
error: function(msg)
{
},
failure: function(msg)
{
}
});
};
$('#btnSave').click(function()
{
SaveCurrentList();
});
});
/* json data snip */
{"FormData":{"Control":{"CustomerId":"12345y6","CustomerName":"Joe Customer"},"PhonesBlock":{"Phone":[{"PhoneNumber":"234-233-2322","PhoneName":"son harry"},{"PhoneNumber":"234-233-2323","PhoneName":"son frank"},{"PhoneNumber":"234-233-2320","PhoneName":"momk"}]}}}
/XML of the form data:/
<FormData>
<Control>
<CustomerId>12345y6</CustomerId>
<CustomerName>Joe Customer</CustomerName>
</Control>
<PhonesBlock>
<Phone>
<PhoneNumber>234-233-2322</PhoneNumber>
<PhoneName>son harry</PhoneName>
</Phone>
<Phone>
<PhoneNumber>234-233-2323</PhoneNumber>
<PhoneName>son frank</PhoneName>
</Phone>
<Phone>
<PhoneNumber>234-233-2321</PhoneNumber>
<PhoneName>momk</PhoneName>
</Phone>
</PhonesBlock>
</FormData>
/* form layout snip */
<div class="control">
<div class="customer">
<input typeof="text" id="CutomerId" />
<input typeof="text" id="CutomerName" />
</div>
<div class="phoneslist" id="PhonesBlock">
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
</div>
</div>
<input id="buttonSave" class="myButton" type="button" value="Save" />
signature of the web service method:
[WebMethod(EnableSession = true)]
public string SaveJson(string FormData)
{
}

Categories