Asp mvc jquery - in place edit - javascript

I have list of divs with some data in there:
<div style="border: 1px solid #dddddd;">
<div id="wrap">
<h3 id="cText">#Model.CommentText</h3>
<a id="runEdit" href="#" >Edit</a>
</div>
</div>
When user click on runEdit link I make edit from this:
e.preventDefault();
var txt = $('#cText').text();
$('#cText').remove();
$('#wrap').prepend('<textarea>' + txt + '</textarea>');
$('#wrap').append('<input type="submit" value="Ok" />');
$('#wrap').append('<input type="submit" value="Cancel" />');
The problem is I added here this two buttons in javascript. But I don't know how to attach some controller action to this buttons?
The problem here is that if I write 5 comments. And click on edit I get 5 edit forms.
$('#editButton').live('click', function (e) {
e.preventDefault();
var container = $(this).closest('.commentWrap');
var itemId = container.attr('id');
var nestId = '#' + itemId;
var txt = $('#commentTextValue').text();
$(nestId + ' #commentTextValue').remove();
$(nestId + ' #editButton').remove();
$(nestId).prepend('<textarea id="editArea">' + txt + '</textarea>');
$(nestId).append('<input type="submit" value="Ok" class="btnOk" />');
})
$('.btnOk').live('click', function (e) {
e.preventDefault();
var container = $(this).closest('.commentWrap');
var itemId = container.attr('id');
var text = container.find('textarea').val();
var nestId = '#' + itemId;
//alert(nestId);
$.ajax({
url: '/Comment/SaveComment',
data: JSON.stringify({ CommentText: text, CommentId: itemId }),
type: 'post',
contentType: 'application/json',
success: function (data) {
if (data.success === true) {
//alert(data.message); // do show/hide stuff here instead of the alert
$(nestId + ' #editArea').remove();
$(nestId + ' .btnOk').remove();
$(nestId).append('<h3 id="commentTextValue">' + data.message + '</h3>');
$(nestId).append('<a id="editButton" href="#">Edit</a>');
}
}
});
});
</script>
<div style="border: 1px solid #dddddd;">
#Html.ActionLink(#Model.Author, "SomeAction")
<div class="commentWrap" id="#Model.CommentId">
<p id="commentTextValue">#Model.CommentText</p>
<a id="editButton" href="#">Edit</a>
</div>
</div>

First add an itemid to the div like this, and convert the id=wrap to a class, as there are more than one of them.
<div class="wrap" id="123"></div>
That way you get a way to reference the id of the item that you are editing.
You should also add a class to the submit button that you inject on the page, fx:
<input type="submit" class="btnOk" value="Ok"/>
Then you can hook up the javascript:
$('.btnOk').live('click',function(e){
e.preventDefault();
var container = $(this).closest('.wrap');
var itemId = container.attr('id');
var text = container.find('textarea')[0].val();
$.ajax({
url: '/mycontroller/savecomment',
data: JSON.stringify({comment: text, id:itemId}), // using JSON2, see below
type: 'post',
contentType: 'application/json',
success: function(data){
if(data.success===true){
alert(data.message); // do show/hide stuff here instead of the alert
}
}
});
});
NOTE: Download the json2 library and add it to you script references - it's a good way to do your json serialization. (https://github.com/douglascrockford/JSON-js)
In your controller you must add an action method to handle the request:
public ActionResult SaveComment(string text, int id)
{
//save your comment for the thing with that id
var result = new {success = true, message = "saved ok"};
return Json(result, JsonRequestBehavior.AllowGet);
}

The answer of Marc is collrect. Surround your code with this. However I strongly recommend you to make as much "html in html" rather than in JavaScript.
The above code could be translated to a better shape, like this,
<div style="border: 1px solid #dddddd;">
<div id="wrap">
<h3 id="cText">#Model.CommentText</h3>
<a id="runEdit" href="#" >Edit</a>
</div>
<div id="editPanel" style="display:none;">
<form action="#Url("Edit", "Whatevercontroller")">
<textarea name="CommentText">#CommentText</textarea>
<input type="submit" value="Ok" />
Cancel
</form>
</div>
</div>
and js would be
function StartEdit() {
$("#wrap").css("display", "none");
$("#editPanel").css("display", "block");
}
function CancelEdit() {
$("#wrap").css("display", "block");
$("#editPanel").css("display", "none");
}
the advantage of this approach that you do not generate too much DOM elements in this case. Otherwise chances tha your JavaScript will become absolutely unmanageable.

You have to put a form tag around your textarea and to set the action of the form by the #Url.Action helper to the needed action.

You need to make Ajax calls to your controller action. Please refer to below link :
http://tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views
You will find a sample there.
Basically, what you need to do is as follows:
var d = "poo=1&bar=2";
$.ajax({
type: "POST",
url: "/home/myaction",
data: d,
success: function (r) {
alert(r.data);
},
complete: function () {
alert("I am done!");
},
error: function (req, status, error) {
//do what you need to do here if an error occurs
alert("error");
}
});

Related

After an AJAX call, my JS code doesnt load until I refresh the page

So i have a project in Laravel, I have added filters, and it filters the products fine. However, when products are filterd my add to cart buttons become unresponsive. I figured after inspecting the rendered code in the browser that the JS was not loaded. However if i manually refresh the page (or refresh in the code with location.reload()) then it works. However I want to avoid manual refresh because then I would lose the colour class added to the button to show that its active filter.
Below is the code for my product file which loads the products in a for loop from the controller:
products.blade.php
<div class="container">
<!--Grid row-->
<div class="row">
#foreach ($products as $p)
<div class="col-lg-3">
<div class="container">
<form action="{{ route('cart.add', $p->id) }}" data-id="{{ $p->id }}" id="addtocart">
<div class="row">
<h5>{{ $p -> name }}</h5>
<button type="button" id="submit" class="button has-shadow is-danger submit is-small">
Add to Cart
</button>
</div>
</form>
</div>
</div>
#endforeach
</div>
<div class="container">
{{ $products ->appends($request->query()) -> links() }}
</div>
</div>
products_show.blade.php - Where the JS is and where the above file is loaded. The issue occurs after the $('body').on('click', '.btn-filter' is called.
#extends ('layouts.app')
#section ('content')
<div class="box text-right">
<div class="row">
<button type="button" name="filter[]" value="Jackets" id="filterJackets" class="button is-info btn-filter">Jackets</button>
<button type="button" name="filter[]" value="Hoodies" id="filterHoodies" class="button is-info btn-filter">Hoodies</button>
</div>
</div>
<section class="products">
#include('product.products')
</section>
#endsection
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$(document)
.ajaxStart(function () {
$("#modal").show();
})
.ajaxStop(function () {
$("#modal").hide();
});
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Pagination
$('body').on('click', '.pagination a', function(e) {
var url = $(this).attr('href');
$.ajax({
url : url
}).done(function (data) {
$('.products').html(data);
}).fail(function () {
alert('Products could not be loaded.');
});
window.history.pushState("", "", url);
});
// Add to cart
$(".submit").click(function (e) {
e.preventDefault();
var p_id = $(this).closest("form").data('id');
var product_id = $("#product_id").val();
var url = $(this).closest('form').attr('action');
$.ajax({
url:url,
method:'POST',
data:{
product_id:product_id
},
success:function(response){
console.log("added to cart success");
},
});
});
$('body').off('click', '.btn-filter', function(e) {
$(this).removeClass("is-success");
});
$(".btn-filter").hover(function(){
$(this).addClass("is-danger");
}, function(){
$(this).removeClass("is-danger");
});
var filters = [];
$('body').on('click', '.btn-filter', function(e) {
e.preventDefault();
$(this).toggleClass('is-success');
filters = []; // reset
$('button[name="filter[]"]').each(function()
{
if ($(this).hasClass("is-success")) {
filters.push($(this).val());
}
});
var url = '{{ route('products.type') }}'+'?filter[storage]='+filters
$.ajax({
url : url
}).done(function (data) {
$('.products').html(data);
}).fail(function () {
alert('Products could not be loaded.');
});
window.history.pushState("", "", url);
});
});
</script>
I am not sure if the php code matters because the problem here is the add to cart button JS is not being called, but here it is anyways:
public function filterByType(Request $request){
$products = QueryBuilder::for(Auth::user()->products())
->allowedFilters(['type'])->paginate()
->appends(request()->query());
// Check if request is from ajax
if ($request->ajax()) {
return view('product.products', ['products' => $products])->render();
}
return view('product.products_show', compact('products'));
}
Thanks.
So i found a hackway to do this, However is there a better solution or a way to fix my issue? And is what i did here bad?:
I added location.reload() to the end of the btn-filter on click which will reload the page since reloading the page fixes the issue for me.
I then added the code below to the top of the script:
var window_url = window.location.href;
var url_filter_params = window_url.substr(window_url.indexOf("=") + 1)
var filter_params_array = url_filter_params.split(',');
$('button[name="filter[]"]').each(function()
{
if ($.inArray($(this).val(), filter_params_array) >= 0){
$(this).addClass('is-success');
}
});
This basically gets the URL parses it to get the params, and then shows adds the is-warning class back to the button to make it appear as selected. The filters also work.

Can I send a form using <h3> tag using js

I want to send a form without using button. I want to send it when the user clicks on the text so can I do it using JS or not. this is my code
function stateChanged() {
if (xmlHttp.readyState==4){
//document.updateForm.qty.value=xmlHttp.responseText;
var val = xmlHttp.responseText;
var res = val.split("#");
var html="<table>";
for(var i=0; i<res.length-1 ; i++ ){
//document.getElementById('results').innerHTML +="<tr><td> <a href='www.google.com'>" + res[i] + '</a></td></tr>';
// html+="<tr><td></form> <a href = "+ 'changeRoles.php?un=' + res[i] + '>'+ res[i] + "</td></tr>";
html+= "<tr><td><form name = 'choose' method='post'> <h3 onclick='document.choose.submit();'>"+res[i]+"</h3> <input type='hidden' name = 'un' value = '"+ res[i]+"'> </form></td></tr>";
}
html+="</table>";
document.getElementById('results').innerHTML =html;
}
}
Technically, yes, it is possible. Just add the target url to the form element's action attribute.
But why would you want to break user expectations and best practices for UI design ?
<table>
<thead/>
<tbody>
<tr>
<td>
<form action="<your url goes here>" name='choose' method='post'>
<h3 onclick='document.choose.submit();'>Whatsup</h3>
<input type='hidden' name = 'un' value = 'blarf'>
</form>
</td>
</tr>
</tbody>
</table>
First define a callback method
call the defined method from <h3> tag
Example is given below.
Try and let me know whether you have any further query
function action1()
{
$.ajax({
url : 'example.com',
type: 'GET',
success : handleData
});
}
<h3 onclick='action1();'>Submit</h3>
It will run. Just copy paste once. Check it. Then let me know if you have any other query.
function action1()
{
$.ajax({
url: 'some_unknown_page.html',
success: function (response) {
alert("I am success");
},
error: function (jqXHR, exception) {
alert("I am clickable");
},
});
}
<html>
<header>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</header>
<body>
<form name = 'choose' action="asdada" method='post'>
<h3 onclick='action1();'>Click Me</h3>
</form>
</body>
</html>

Ajax generated content, unable to hide when onclick

Here is my code:
HTML Code: (Dynamic Generated by ajax).
<div class="btn btn-primary" image-data="imagedata" name-data="name data" artist-data="artist data" country-data="in" id="1252785363" onclick="ajax($(this));return false;">Add Album</div>
<div class="btn btn-primary" image-data="imagedata" name-data="name data" artist-data="artist data" country-data="in" id="1252985363" onclick="ajax($(this));return false;">Add Album</div>
<div class="btn btn-primary" image-data="imagedata" name-data="name data" artist-data="artist data" country-data="in" id="1256985363" onclick="ajax($(this));return false;">Add Album</div>
Each DIV has unique ID!
Javascript:
function ajax($this) {
var id = $this.attr("id");
var image_data = $this.attr("image-data");
var name_data = $this.attr("name-data");
var artist_data = $this.attr("artist-data");
var country_data = $this.attr("country-data");
$.ajax({
method: "POST",
url: "URL to Call",
dataType: "text",
data: {
image: image_data,
artist: artist_data,
name: name_data,
country: country_data,
id: id
},
success: function(response) {
console.log(response);
$(id).hide();
alert(id);
}
});
}
Its return the response, its alert the ID, but somehow i am unable to find, i try $(id).css('display', 'none'); , toggle but no luck!
If possible please let me know the solution!
You need to use a # prefix to select an ID.
$("#" + id).hide();
The id attribute you are reading does not contain the # selector, which JQuery wants when you search for the element.
If instead you use $("#" + id).hide(); I think you will get the result you are looking for.

JQuery function call firing multiple times

I'm trying to call a function for an html element using jquery. I'm struggling with this has been hours and I can't figure out what is wrong.
I have an answer which I want to mark as solved. A question have multiple answers.
As far as I know the function is being fired the number of answers I have in the question. If I have two answers, the function will run twice and so on.
$(document).ready(function () {
$(".accepted.ans").on('click', function (e) {
e.preventDefault();
var parent = $(this).closest('.accept');
console.log(parent);
var current = $(this);
console.log(current);
var url = parent.data('url');
var qid = parent.data('question');
var aid = parent.data('answer');
$.get(url + '?question=' + qid + '&answer=' + aid, function (data) {
console.log("Reading...");
data = $.parseJSON(data);
console.log(aid);
console.log(e);
setAcceptedStatus(current, data.result);
});
});
});
function setAcceptedStatus(object, status) {
if (status === true) {
object.addClass('active');
}
}
This is my jQuery function. The one that I want to be called exactly once for each answer when I press the accept ans div element, which is:
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}" >
<div class="accept"
title="Accept this answer"
data-url="{url('controller/api/questions/mark_as_solved')}"
data-refresh="{url('controller/api/questions/refresh_accepted_answers')}"
data-answer="{$answer['answerid']}"
data-question="{$question['publicationid']}">
<div class="accepted ans"
id="{$answer['answerid']}"
title="Unnacept this answer">
</div>
</div>
</blockquote>
I thought this was happening because everytime I want to call that function , since I have $(".accepted.ans") it will apply to all the accepted ans it can find on the document. So I thought in adding an id to the class, something like:
id="{$answer['answerid']}"
but as I read somewhere here, it is supposed to work without that.
I really don't know why it triggers more than once, I did all kind of debug, checked the html structure and everything seems flawless.
Any kind soul got an idea in what is wrong?
Regards
I suspect that somehow the $(document).ready() function is executed as many times as your answers, so the click event handler is binded the same number of times for each answer. Perhaps it's the template that does that?
If that's indeed the problem and you can't find a solution for the template, try changing
$(".accepted.ans").on('click', function (e) {
to
$(".accepted.ans").off('click').on('click', function (e) {
to unbind all click event handlers but the last one.
try changing .closest(... to .parent(). Snippet below...
$(document).ready(function() {
$(".accepted.ans").on('click', function(e) {
e.preventDefault();
var current = $(this),
parent = current.parent();
var url = parent.data('url');
var qid = parent.data('question');
var aid = parent.data('answer');
console.log(aid);
$.get(url + '?question=' + qid + '&answer=' + aid, function(data) {
console.log("Reading...");
data = $.parseJSON(data);
console.log(aid);
console.log(e);
setAcceptedStatus(current, data.result);
});
});
});
function setAcceptedStatus(object, status) {
if (status === true) {
object.addClass('active');
}
}
.ans {
position: static;
width: 90%;
height: 5em;
background: #f90;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}">
<div class="accept" title="Accept this answer" data-url="{url('controller/api/questions/mark_as_solved')}" data-refresh="{url('controller/api/questions/refresh_accepted_answers')}" data-answer="one" data-question="{$question['publicationid']}">
<div class="accepted ans" id="{$answer['answerid']}" title="Unnacept this answer">
</div>
</div>
</blockquote>
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}">
<div class="accept" title="Accept this answer" data-url="{url('controller/api/questions/mark_as_solved')}" data-refresh="{url('controller/api/questions/refresh_accepted_answers')}" data-answer="two" data-question="{$question['publicationid']}">
<div class="accepted ans" id="{$answer['answerid']}" title="Unnacept this answer">
</div>
</div>
</blockquote>
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}">
<div class="accept" title="Accept this answer" data-url="{url('controller/api/questions/mark_as_solved')}" data-refresh="{url('controller/api/questions/refresh_accepted_answers')}" data-answer="three" data-question="{$question['publicationid']}">
<div class="accepted ans" id="{$answer['answerid']}" title="Unnacept this answer">
</div>
</div>
</blockquote>
Using jQuery, you need to prevent it's function listened by other event attached to its parental tags. So try the stopPropagation(); instead.
$(document).ready(function () {
$(".accepted.ans").on('click', function (e) {
e.stopPropagation();
e.preventDefault();
var parent = $(this).closest('.accept');
console.log(parent);
var current = $(this);
console.log(current);
var url = parent.data('url');
var qid = parent.data('question');
var aid = parent.data('answer');
$.get(url + '?question=' + qid + '&answer=' + aid, function (data) {
console.log("Reading...");
data = $.parseJSON(data);
console.log(aid);
console.log(e);
setAcceptedStatus(current, data.result);
});
});
});
function setAcceptedStatus(object, status) {
if (status === true) {
object.addClass('active');
}
}

prevent double click on button in javascript

<script type="text/javascript">
$(document).ready(function () {
$("#submit").on("click", function () {
$(this).attr('disabled', true);
var taskid = num;
var loadnew = 1;
var guessnum = $("input[name=guessnum]:checked").val();
if (guessnum != 1 && guessnum != 2) {
alert("You could not submit an empty answer");
loadnew = 0;
location.href = "/minions/peerprediction1.php";
}
else if (loadnew == 1) {
finishedTask += 1;
}
var starttime = $("#timestart").val();
var timecost = starttime;
$.ajax({
type: "post",
url: "GameMysql.php",
data: "taskid=" + taskid + "&guessnum=" + guessnum + "&effort=" + effort + "&finishedTask=" + finishedTask + "&time=" + timecost,
success: function (data) {
}
});
});
});
</script>
<form>
<a class="button" id="submit"><span>&#10003</span>Submit report</a>
</form>
I want to make sure the form with same answers do not submit twice, and disable the button, but it does not truly work. For I click it twice the finished task number increased by 2
I already see the answer here Prevent double submission of forms in jQuery
and tried, but still could not make it work
Use the button element, it will provide the functionality you are after. It can be styled to look like an anchor. Less issues trying to get it working as intended across all browsers.
$("#submit").on("click",function(){
$(this).attr('disabled', true);
console.log('disabled');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="button" id="submit"> <span>&#10003</span> Submit report</button>
You should use a button instead of an anchor, anchors dont support the disabled attribute
<button id="submit">Submit Report</button>

Categories

Resources