Partial View via Ajax all Javascript References are broken - asp.net

i have a PartialView in my MVC Appliction, which returns my View if there are any Errors in the ModelState. In the _Layout site are many javascript ( jQuery, JQuery.validate, ... ) references which i use in the partai view.
Here the Code:
Javascript submit:
$(function () {
$('form').submit(function (e) {
e.preventDefault();
if ($('form').valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (!result.Success) {
$('#formcontent').html(result); // Show PartailView with Validationmessages
}
else {
}
}
});
}
});
});
Parent Site:
<div id="formcontent" class="tc-form">
#{ Html.RenderPartial( "_ConfigurationPartial", Model ); }
</div>
Partial View:
#model SettingsViewModel
#{ Layout = null; }
#using( Html.BeginForm() )
{
#Html.ValidationSummary( false, SystemStrings.ValidationSummaryMessage )
<ol class="last">
<li class="row">
#Html.LabelFor( m => m.PasswordMinimumLength )
#Html.EditorFor( m => m.PasswordMinimumLength )
#Html.ValidationMessageFor( m => m.PasswordMinimumLength, "*" )
</li>
<li class="row">
#Html.LabelFor( m => m.PasswordNeverExpires )
#Html.EditorFor( m => m.PasswordNeverExpires )
#Html.ValidationMessageFor( m => m.PasswordNeverExpires, "*" )
</li>
<li class="row">
#Html.LabelFor( m => m.PasswordExpirationValue )
#Html.EditorFor( m => m.PasswordExpirationValue )
#Html.ValidationMessageFor( m => m.PasswordExpirationValue, "*" )
#Html.EditorFor( m => m.PasswordExpirationUnit )
#Html.ValidationMessageFor( m => m.PasswordExpirationUnit, "*" )
</li>
</ol>
<div class="tc-form-button">
<input type="submit" value="Save" title="Save" class="t-button t-state-default" />
#Html.ActionLink( "Cancel", "Configuration", "System", null, new { #class = "t-button" } )
</div>
}
<script type="text/javascript">
jQuery(document).ready(function () {
$('#PasswordNeverExpires').change(function () {
setState($(this).is(':checked'));
});
});
function setState(isDisabled) {
if (isDisabled) {
// ...
}
else {
// ...
}
}
Controller:
[HttpPost]
public ActionResult Configuration( SettingsViewModel model )
{
if( !ModelState.IsValid )
{
this.PopulateViewData();
return PartialView( "_ConfigurationPartial", model );
}
else
{
// ... do save
return Json( new { Success = true }, JsonRequestBehavior.AllowGet );
}
}
If the partialView is load via ajax all my Javascript are broken. There is no second ajax submit, it is a normal post. So the partialvew is rendered without any layout informations. It seems that all the javascript references are not found. Is there any way to refresh the DOM or something else? Must i have all the javascript in the PartailView? What is the correct way for this?
Regards

This code is outside of Partial View:
<script type="text/javascript">
jQuery(document).ready(function () {
var oldvalue=$('#PasswordNeverExpires').val();
$('#PasswordNeverExpires').change(function(){
oldvalue=$(this).val();
})
});
</script>
Then I change your code in PartialView a little:
jQuery(document).ready(function () {
if($('#PasswordNeverExpires').val()!=oldvalue){
//your scripts put here.
}
});
The above code was not tested but It should work.

Your problem is that you bind the submit event to the form when the page is loaded for the first time. When you reload the form through ajax you need to rebind the submit event to your new form.
You can also live bind the event, which you do only once
$("form").live("submit", function(e) {
e.preventDefault();
if ($('form').valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
if (!result.Success) {
$('#formcontent').html(result); // Show PartailView with Validationmessages
}
else {}
}
});
}
});
read more here

Related

Easy admin : add checkbox or a button to display listAction

i'm new to Symfony (SF 3)/
i'm trying to put a checkbox or a button in an easy admin panel listAction to display connected or disconnected users in a list.
What i want to do is: i load my users list with only connected users, and when i click on checkbox "display all users", to reload the list with all users, disconnected and connected.
I don't know if i have to override listAction() and how, or just using createListQueryBuilder with an ajax call.
I have try this in my controller
protected function createListQueryBuilder($entityClass, $sortDirection, $sortField = null, $dqlFilter = null)
{
$response = parent::createListQueryBuilder($entityClass, 'ASC', 'name', $dqlFilter);
if ($this->request->query->get('connected') == 'all') {
$response->Where('entity.connected in (0, 1)');
} else {
$response->Where('entity.connected = 0 ');
}
return $response;
}
In my twig :
<div class="row">
<div class="p-3 mb-2 bg-light text-dark">
<input type="checkbox" name="checkbox" id="connected">Display all users</b><br>
</div>
<div class="clearfix"></div>
{% block body_javascript %}
{% if 'list' == app.request.get('action') %}
<script type="text/javascript">
$(function(){
$('#connected').click(function(event) {
$.ajax({
type: "POST",
url: '/?entity=user&action=list&connected=all',
data: {
'connected': 'all',
},
success: function (data) {
alert('it worked');
},
error: function () {
alert('it broke');
},
complete: function () {
alert('it completed');
}
});
});
});
I'm a little lost and I can't get anywhere.
can you guide me ?
Samantha

Two recaptcha controls, one of them is not working

I have two reCaptcha V2 controls within two forms in one page, one is visible another is invisible. All is fine except the invisible one's data-callback callback - submitSendForm() did not get called. Once I removed the visible one, the invisible one starts working.
So the process is like once user completed the first visible challenge then the second form(within same page) will show with the invisible one, that's when the call back failed to be called.
It hasn't to be one visible and another invisible. But I found this to be easy when you want to have multiple controls.
Here is the code:
using (Html.BeginForm("Verify", "CertificateValidation", FormMethod.Post, new { id = "verifyForm" }))
{
<div class="form-group">
<div class="g-recaptcha" data-sitekey='site-key' data-callback="enableBtn"
style="transform: scale(0.66); transform-origin: 0 0;">
</div>
<div class="col-sm-3">
<button type="submit" id="verify" disabled>Verify</button>
</div>
</div>
}
using (Html.BeginForm("Send", "CertificateValidation", FormMethod.Post, new { id = "sendForm" }))
{
<div id='recaptcha1' class="g-recaptcha"
data-sitekey='site-key'
data-callback="submitSendForm"
data-size="invisible"></div>
<button type="submit">Send</button>
}
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script type="text/javascript">
function submitSendForm() {
console.log('captcha completed.');
$('#sendForm').submit();
}
$('#sendForm').submit(function (event) {
console.log('form submitted.');
if (!grecaptcha.getResponse()) {
console.log('captcha not yet completed.');
event.preventDefault(); //prevent form submit
grecaptcha.execute();
} else {
console.log('form really submitted.');
}
});
var enableBtn = function (g_recaptcha_response) {
$('#verify').prop('disabled', false);
};
$(document).ready(function () {
$('#verify').click(function () {
$captcha = $('#recaptcha');
response = grecaptcha.getResponse();
if (response.length === 0) {
return false;
} else {
return true;
}
});
});
</script>
I got it figured out somehow:
var CaptchaCallback = function () {
grecaptcha.render('RecaptchaField1', { 'sitekey': 'site-key', 'callback': 'enableBtn' });
window.recaptchaField2Id = grecaptcha.render('RecaptchaField2', { 'sitekey': 'site-key', 'callback': 'submitSendForm', 'size': 'invisible' });
};
function submitSendForm() {
$('#sendForm').submit();
}
$('#sendForm').submit(function (event) {
if (!grecaptcha.getResponse(window.recaptchaField2Id)) {
event.preventDefault();
grecaptcha.execute(window.recaptchaField2Id);
}
});
using (Html.BeginForm("Verify", "CertificateValidation", FormMethod.Post, new { id = "verifyForm" }))
{
<div class="form-group">
<div style="transform: scale(0.66); transform-origin: 0 0;" id="RecaptchaField1"></div>
<div class="col-sm-3">
<button type="submit" id="verify" disabled>Verify</button>
</div>
</div>
}
using (Html.BeginForm("Send", "CertificateValidation", FormMethod.Post, new { id = "sendForm" }))
{
<div id="RecaptchaField2"></div>
<button type="submit">Send</button>
}
This one worked for me, clean and easy.
Javascript
var reCaptcha1;
var reCaptcha2;
function LoadCaptcha() {
reCaptcha1 = grecaptcha.render('Element_ID1', {
'sitekey': 'your_site_key'
});
reCaptcha2 = grecaptcha.render('Element_ID2', {
'sitekey': 'your_site_key'
});
};
function CheckCaptcha1() {
var response = grecaptcha.getResponse(reCaptcha1);
if (response.length == 0) {
return false; //visitor didn't do the check
};
};
function CheckCaptcha2() {
var response = grecaptcha.getResponse(reCaptcha2);
if (response.length == 0) {
return false; //visitor didn't do the check
};
};
HTML
<head>
<script src="https://www.google.com/recaptcha/api.js?onload=LoadCaptcha&render=explicit" async defer></script>
</head>
<body>
<div id="Element_ID1"></div>
<div id="Element_ID1"></div>
</body>

pass parameter from View to Controller in asp mvc

I am trying to pass parameter from view to controller,
This is my View:
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#foreach (var pricedetails in ViewBag.PriceTotal)
{
<div style="text-align:center; clear:both ">
<h5 class="product-title">#pricedetails.Title</h5>
</div>
<div class="product-desciption" style="height:40px">#pricedetails.Descriptions</div>
<p class="product-desciption product-old-price"> #pricedetails.PricePoints</p>
<div class="product-meta">
<ul class="product-price-list">
<li>
<span class="product-price">#pricedetails.PricePoints</span>
</li>
<li>
<span class="product-save">Get This Free</span>
</li>
</ul>
<ul class="product-actions-list">
<input type="submit" name='giftid' value="Get Gift"
onclick="location.href='#Url.Action("Index", new { id = pricedetails.PriceId })'" />
</ul>
</div>
}
}
my action method:
On submit it reaches the Action Method, but I am not able to get the PriceId for each Price
[HttpPost]
public ActionResult Index(int id=0) // here PriceId is not passed on submit
{
List<Price_T> priceimg = (from x in dbpoints.Price_T
select x).Take(3).ToList(); ;
ViewBag.PriceTotal = priceimg;
var allpoint = singletotal.AsEnumerable().Sum(a => a.Points);
var price = from x in dbpoints.Price_T
where x.PriceId == id
select x.PricePoints;
int pricepoint = price.FirstOrDefault();
if (allpoint < pricepoint)
{
return Content("<script language='javascript' type='text/javascript'>alert('You are not elgible');</script>");
}
else
{
return Content("<script language='javascript' type='text/javascript'>alert('You are elgible');</script>");
}
return View("Index");
}
Url Routing:
routes.MapRoute(
name: "homeas",
url: "Index/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
May I know what wrong I am doing ?
Please use the following in your cshtml page
#foreach (var item in Model)
{
#Html.ActionLink(item.PriceDetails, "GetGift", new { priceID = item.priceID }, new { #class = "lnkGetGift" })
}
<script type="text/javascript" src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("a.lnkGetGift").on("click", function (event) {
event.preventDefault();
$.get($(this).attr("href"), function (isEligible) {
if (isEligible) {
alert('eligible messsage');
}
else
{
alert('not eligible messsage');
}
})
});
});
</script>
and in controller
[HttpGet]
public JsonResult GetGift(int priceID)
{
List<Price_T> priceimg = (from x in dbpoints.Price_T
select x).Take(3).ToList(); ;
ViewBag.PriceTotal = priceimg;
var allpoint = singletotal.AsEnumerable().Sum(a => a.Points);
var price = from x in dbpoints.Price_T
where x.PriceId == id
select x.PricePoints;
int pricepoint = price.FirstOrDefault();
if (allpoint < pricepoint)
{
return Json(false, JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
Please change your parameters according to the method param and price entity
Hope this helps.
I suggest you get rid of the Html.BeginForm(). Just leave the for...loop and define your "Get Gift" button like this:
<input type="button" id='giftid' name='giftid' value="Get Gift" onclick="getGift(#(pricedetails.PriceId))'" />
Then, at the bottom of the view file where the Get Gift button is located, define some JavaScript:
<script type="text/javascript">
function getGift(priceId) {
$.ajax({
type: 'GET',
url: '#Url.Action("Index", "Home")',
data: { priceId: priceId },
contentType : "json",
success:function(data){
// Do whatever in the success.
},
error:function(){
// Do whatever in the error.
}
});
</script>
By using an ajax call to get the gift data, you don't have to submit anything. This makes things a lot easier in your case. Pressing the Get Gift button simply makes an ajax call.
I don't have time to try this out myself, but hopefully the above example should get you up and running.
EDIT:
I've managed to sneak in some time to come up with an example.
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
var items = new List<int>();
items.Add(1);
items.Add(2);
items.Add(3);
return View(items);
}
public ActionResult GetGift(int priceId)
{
return RedirectToAction("Index"); // You'll be returning something else.
}
}
View
#model List<int>
#foreach (var price in Model)
{
<input type="button" id='giftid' name='giftid' value="Get Gift" onclick="getGift(#(price))" />
}
<script type="text/javascript">
function getGift(priceId) {
$.ajax({
type: 'GET',
url: '#Url.Action("GetGift", "Home")',
data: { priceId: priceId },
contentType: "json",
success: function(data) {
// Do whatever in the success.
},
error: function() {
// Do whatever in the error.
}
});
}
</script>
Hope this helps you.
I think you should correct here
<input type="button" name='giftid' value="Get Gift"
onclick="location.href='#Url.Action("Index", new { id = pricedetails.PriceId })'" />

Tracker afterFlush error : Cannot read value of a property from data context in template rendered callback

I'm making a simple Meteor app that can redirect to a page when user click a link.
On 'redirect' template, I try get the value of property 'url' from the template instance. But I only get right value at the first time I click the link. When I press F5 to refresh 'redirect' page, I keep getting this error message:
Exception from Tracker afterFlush function: Cannot read property 'url' of null
TypeError: Cannot read property 'url' of null
at Template.redirect.rendered (http://localhost:3000/client/redirect.js?abbe5acdbab2c487f7aa42f0d68cf612f472683b:2:17)
at null.
This is where debug.js points to: (line 2)
if (allArgumentsOfTypeString)
console.log.apply(console, [Array.prototype.join.call(arguments, " ")]);
else
console.log.apply(console, arguments);
} else if (typeof Function.prototype.bind === "function") {
// IE9
var log = Function.prototype.bind.call(console.log, console);
log.apply(console, arguments);
} else {
// IE8
Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
}
Can you tell me why I can't read the value of 'url' property from template data context in template rendered callback?
This is my code (for more details, you can visit my repo):
HTML:
<template name="layout">
{{>yield}}
</template>
<template name="home">
<div id="input">
<input type="text" id="url">
<input type="text" id="description">
<button id="add">Add</button>
</div>
<div id="output">
{{#each urls}}
{{>urlItem}}
{{/each}}
</div>
</template>
<template name="redirect">
<h3>Redirecting to new...{{url}}</h3>
</template>
<template name="urlItem">
<p><a href="{{pathFor 'redirect'}}">
<strong>{{url}}: </strong>
</a>{{des}}</p>
</template>
home.js
Template.home.helpers({
urls: function(){
return UrlCollection.find();
}
});
Template.home.events({
'click #add': function() {
var urlItem = {
url: $('#url').val(),
des: $('#description').val()
};
Meteor.call('urlInsert', urlItem);
}
});
redirect.js
Template.redirect.rendered = function() {
if ( this.data.url ) {
console.log('New location: '+ this.data.url);
} else {
console.log('No where');
}
}
Template.redirect.helpers({
url: function() {
return this.url;
}
});
router.js
Router.configure({
layoutTemplate: 'layout'
})
Router.route('/', {
name: 'home',
waitOn: function() {
Meteor.subscribe('getUrl');
}
});
Router.route('/redirect/:_id', {
name: 'redirect',
waitOn: function() {
Meteor.subscribe('getUrl', this.params._id);
},
data: function() {
return UrlCollection.findOne({_id: this.params._id});
}
});
publication.js
Meteor.publish('getUrl', function(_id) {
if ( _id ) {
return UrlCollection.find({_id: _id});
} else {
return UrlCollection.find();
}
});
Add this
Router.route('/redirect/:_id', {
name: 'redirect',
waitOn: function() {
Meteor.subscribe('getUrl', this.params._id);
},
data: function() {
if(this.ready()){
return UrlCollection.findOne({_id: this.params._id});
}else{
console.log("Not yet");
}
}
});
Tell me if works.
With help from my colleague, I can solve the problem.
My problem comes from wrong Meteor.subscribe syntax. In my code, I forget "return" in waitOn function. This will make Meteor do not know when the data is fully loaded.
Here is the right syntax:
waitOn: function() {
return Meteor.subscribe('getUrl', this.params._id);
}

Partial view render on button click

I have Index view:
#using System.Web.Mvc.Html
#model MsmqTestApp.Models.MsmqData
<!DOCTYPE html>
<html>
<head>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<meta name="viewport" content="width=device-width" />
<title>MsmqTest</title>
</head>
<body>
<div>
<input type="submit" id="btnBuy" value="Buy" onclick="location.href='#Url.Action("BuyItem", "MsmqTest", new { area = "Msmq" })'" />
<input type="submit" id="btnSell" value="Sell" onclick="location.href='#Url.Action("SellItem", "MsmqTest", new { area = "Msmq" })'" />
</div>
<div id="msmqpartial">
#{Html.RenderPartial("Partial1", Model); }
</div>
</body>
</html>
and partial:
#using System.Web.Mvc.Html
#model MsmqTestApp.Models.MsmqData
<p>
Items to buy
#foreach (var item in Model.ItemsToBuy)
{
<tr>
<td>#Html.DisplayFor(model => item)
</td>
</tr>
}
</p>
<p>
<a>Items Selled</a>
#foreach (var item in Model.ItemsSelled)
{
<tr>
<td>#Html.DisplayFor(model => item)
</td>
</tr>
}
</p>
And controller:
public class MsmqTestController : Controller
{
public MsmqData data = new MsmqData();
public ActionResult Index()
{
return View(data);
}
public ActionResult BuyItem()
{
PushIntoQueue();
ViewBag.DataBuyCount = data.ItemsToBuy.Count;
return PartialView("Partial1",data);
}
}
How to do that when i Click one of button just partial view render, now controller wants to move me to BuyItem view ;/
The first thing to do is to reference jQuery. Right now you have referenced only jquery.unobtrusive-ajax.min.js but this script has dependency on jQuery, so don't forget to include as well before it:
<script src="#Url.Content("~/Scripts/jquery.jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Now to your question: you should use submit buttons with an HTML form. In your example you don't have a form so it would be semantically more correct to use a normal button:
<input type="button" value="Buy" data-url="#Url.Action("BuyItem", "MsmqTest", new { area = "Msmq" })" />
<input type="button" value="Sell" data-url="#Url.Action("SellItem", "MsmqTest", new { area = "Msmq" })" />
and then in a separate javascript file AJAXify those buttons by subscribing to the .click() event:
$(function() {
$(':button').click(function() {
$.ajax({
url: $(this).data('url'),
type: 'GET',
cache: false,
success: function(result) {
$('#msmqpartial').html(result);
}
});
return false;
});
});
or if you want to rely on the Microsoft unobtrusive framework you could use AJAX actionlinks:
#Ajax.ActionLink("Buy", "BuyItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" })
#Ajax.ActionLink("Sell", "SellItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" })
and if you want buttons instead of anchors you could use AJAX forms:
#using (Ajax.BeginForm("BuyItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Buy</button>
}
#using (Ajax.BeginForm("SellItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Sell</button>
}
From what I can see you have already included the jquery.unobtrusive-ajax.min.js script to your page and this should work.
Maybe not the solution you were looking for but, I would forget about partials and use Javascript to call the server to get the data required and then return the data to the client as JSON and use it to render the results to the page asynchronously.
The JavaScript function;
var MyName = (function () {
//PRIVATE FUNCTIONS
var renderHtml = function(data){
$.map(data, function (item) {
$("<td>" + item.whateveritisyoureturn + "</td>").appendTo("#msmqpartial");
});
};
//PUBLIC FUNCTIONS
var getData = function(val){
// call the server method to get some results.
$.ajax({ type: "POST",
url: "/mycontroller/myjsonaction",
dataType: "json",
data: { prop: val },
success: function (data) {
renderHtml();
},
error: function () {
},
complete: function () {
}
});
};
//EXPOSED PROPERTIES AND FUNCTIONS
return {
GetData : getData
};
})();
And on the Server....
public JsonResult myjsonaction(string prop)
{
var JsonResult;
// do whatever you need to do
return Json(JsonResult);
}
hope this helps....

Resources