I'm trying to throw up a dialog window in MVC without using an AjaxActionLink. I'm using jquery ui 1.8.13 in this example.
Please consider the following snippets:
public class ModalViewModel
{
public string Title { get; set; }
public string Description { get; set; }
}
And the controller:
private ActionResult GetVisitors(VisitorSearchViewModel model)
{
VisitorSearchResponse response =
.... Omitted for brevity
if (response.Success)
{
return View("VisitorList", response.Visitors.ToList());
}
else
{
return RedirectToAction("Error");
}
}
public PartialViewResult Error()
{
return PartialView("Modal",
new ModalViewModel()
{
Title = "Test Title",
Description = "Test Description"
});
}
And finally, the Modal shared view:
#model CraftTraxNG.Model.ViewModels.ModalViewModel
<script type="text/javascript">
$(document).ready(function () {
$("#errorMessage").dialog(
{ autoOpen: true,
title: '#Model.Title',
width: 500,
height: 100,
modal: true,
buttons:{ "OK": function () {
$(this).dialog("close"); }
}
});
});
<div id="errorMessage" style="display:none;">
#Model.Description
</div>
When an error is encountered, it'll write out the partial view contents; ie., it successfully creates the dialog window with the appropriate styles. My problem is I want render the partial view on something on the view I'm currently on. I've never used it in this fashion before. As of now, when it renders that partial view, I lose the contents of the view I'm currently on.
Typically, I can use an AjaxActionLink and just set a div tag I want the dialog to render to and either replace it or insert it after, before, etc.
In this case, I'm heading out to the service and grabbing a response server-side and if it's unsuccessful, I need a way to replace some div tag on the regular view with this partial view.
Any help is appreciated.
Thank you.
I have run into this issue and I have not yet come up with an ideal solution. Here is what I normally do.
Click Me
$(function() {
$("#loadsContentOrError").click(e){
e.preventDefault();
$.ajax({
url: '<%: Url.Action("Error") %>',
success: function(html) {
html = $(html);
if(html.find('.errorMessage').length > 0) {
$('#divToLoadContentTo").append(html);
} else {
$('#divToLoadContentTo").html(html);
}
}
});
});
});
This is pretty rough but it gives you a good starting point.
Related
I'm developing a .NET Core 3.1 Razor Pages Application. One of the Razor Pages within my app Posts the contents of a TextArea using AJAX. This works as expected, however, when I use CKEditor 5 https://ckeditor.com/ckeditor-5/ and turn the TextArea into a WYSIWYG Editor, I can no longer Post the values within the editor.
Please note, the CKEditor loads as expected and there are no errors when I use Developer Tools within Google Chrome.
PageModel
[BindProperty]
public InputModel Input { get; set; }
public PartialViewResult OnPostMyTestPartial()
{
//Some logic then return data for partial
}
public class InputModel
{
public int Id { get; set; }
public string Narrative { get; set; }
}
CSHTML
<form>
<!-- Other html -->
<textarea asp-for="Input.Narrative"></textarea>
<button class="btn btn-primary" id="load">Update</button>
</form>
JQuery
$(document).ready(function () {
$('#load').on('click', function (evt) {
evt.preventDefault();
$.post("/MyPage/Index?handler=MyTestPartial", $('form').serialize(), function (data) {
$("#myPartial").html(data);
});
});
ClassicEditor
.create(document.querySelector('#Input_Narrative'), {
toolbar: ['heading', '|', 'bold', 'italic', 'link']
})
.then(editor => {
window.editor = editor;
})
.catch(err => {
console.error(err.stack);
});
});
When I comment out the ClassicEditor code in my JQuery file so that the TextArea remains purely as a TextArea, I can see through the Developer Tools and debugging in Visual Studio that the value is Posted successfully:
However, when I make the TextArea into an editor using the CKEditor and attempt to Post data, the data is not posted.
Can someone please help?
Thanks.
You need to manually transfer the content of the editor to the form control:
$('#load').on('click', function (evt) {
evt.preventDefault();
$('#Input_Narrative').val(CKEDITOR.instances['Input_Narrative'].getData());
$.post("/MyPage/Index?handler=MyTestPartial", $('form').serialize(), function (data) {
$("#myPartial").html(data);
});
});
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/saving-data.html#manually-retrieving-the-data
I have a few viewmodels, which contains a few functions like:
public override string ToString()
{
return $"{M_IV_ID} {M_IV_INVOICEAMOUNT} {M_IV_MANDANT} {M_IV_TOTALAMOUNT} {M_IV_VEHICLE_PURCHASE} {M_IV_URGENT}";
}
And update / insert functionalities. All of them work. I wrote them separately from my Asp.NET project and tested them since I wanted to do my back end first.
Now I tried to use those functions in my Asp.NET application:
First I get Data from the db in my Controller:
M_IV_INVOICE invoice = QueryBuilder.GetFirstOrDefault(new M_IV_INVOICE(), #"WHERE M_IV_ID IN (75693)");
And pass it to my view:
public ActionResult Index()
{
return View(invoice);
}
Now I tried to use my toString() method just to see if it works:
<form id="formUpdate" runat="server">
<div>
<asp:button id="Button" class="btn btn-primary" runat="server">Update</asp:button>
</div>
</form>
#{
string MyFunction()
{
return Model.ToString();
}
}
#section Scripts
{
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
var button = document.getElementById('Button');
button.addEventListener('click', function () {
var test = "#MyFunction()";
console.log(test);
});
});
</script>
}
And if I do this, it works, and I get my model values printed in the browser console.
If I try to use my Update function instead of the toString() method:
public bool Update()
{
using (IDbConnection conn = ConnectionManager.GetConnection())
{
try
{
conn.Query(QueryBuilder.BuildUpdateForEntity(this, string.Format(" WHERE {0} = {1}", GetKey().Item1, GetKey().Item2)));
return true;
}catch(Exception e)
{
// TODO: Exceptionhandling
}
}
return false;
}
I get a Ora Exception right when the page loads, no button click performed:
Oracle.DataAccess.Client.OracleException: ORA-00936: missing expression
I struggle with understanding why, though.
The select I perform in my controller to get the data in the first place is working just fine, and as I said, if I print my model on button click, it works too.
What am I missing?
Edit:
It seems like the function is directly called while the eventhandler is added and since it has no data at the time, the ORA error is occurring.
But why? I don't understand this behavior.
Another Edit:
It has indeed something to do with the model isn't ready or something:
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
var button = document.getElementById('Button');
button.addEventListener('click', function () {
setTimeout(() => { console.log("#MyFunction()") }, 3000);
});
});
</script>
I added the delay and no error on loading the page.
But that would be just a band aid, not a solution.
If someone has an idea how to prevent that behavior, I would appreciate it.
The #{}symbol is used to write server-side C# or VB code with HTML code, so in the javascript, when you use the #MyFunction() function, the Myfunction will execute. You could set a break point in the MyFunction and the button click event to check it, no matter using the ToString() method or the Update() method, they will work when the DOMContent Loaded. So, when use the Update() method, you will meet the missing expression error.
Based on your description, you want to do some action (call the server-side function/method) when user clicks the button, right? If that is the case, I suggest in the controller you can add the Myfunction and Update action methods, then, in the button click event, you can use JQuery get(), post() or Ajax method to call the action method, refer the following code:
Controller:
[HttpPost]
public JsonResult AjaxMethod(string name)
{
PersonModel person = new PersonModel
{
Name = name,
DateTime = DateTime.Now.ToString()
};
return Json(person);
}
and View Page:
<input type="text" id="txtName" />
<input type="button" id="btnGet" value="Get Current Time" />
#section Scripts{
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
$(function () {
$("#btnGet").click(function () {
$.ajax({
type: "POST",
url: "/Test/AjaxMethod",
data: { name: $("#txtName").val() },
success: function (response) {
alert("Hello: " + response.name + " .\nCurrent Date and Time: " + response.dateTime);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
});
});
</script>
}
I am preparing one PhoneJS application. In that I am trying to put one simple butotn inside the view using the following code but not able to see that button and It's showing only loading icon...
home.html
<div data-options="dxView : { name: 'home', title: 'Home' } " >
<div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
<p>Welcome</p>
<div data-bind="dxButton: { text: 'Click me!', clickAction: showHelloWorld }"></div>
</div>
</div>
home.js
MyApp.home = function (params) {
var viewModel = {
// Put the binding properties here
var showHelloWorld = function() {
alert("Hello world!");
};
ko.applyBindings(myViewModel);
return viewModel;
};
Anyone can help me please?
Your view model code is not well-formed:
MyApp.home = function () {
var viewModel = {
showHelloWorld: function() {
alert("Hello world!");
}
};
return viewModel;
};
viewModel should be valid js object.
You also shouldn't call applyBindings. It will be called by framework.
You should create the HtmlApplication and specify app routing. Not sure, maybe you've done it already.
Here is working fiddle:
http://jsfiddle.net/tabalinas/jb537/
Check out this tutorial "how to build you first PhoneJS app": http://phonejs.devexpress.com/Documentation/Tutorial/Getting_Started/Your_First_Application?version=13_2
How can i dynamically load a Partial View?
I mean I have this view, lets say ListProducts, there I select some dropdownlists with products, etc, and with the selected values from those I wanna fill a partial view, which would be in a div that was invisible but after onchange() event would become visible and with the data from the specific selected items.
Use jQuery's $.load() with a controller action that returns a partial view.
For example:
HTML
<script type="text/javascript">
$(document).ready(function()
{
$("#yourselect").onchange(function()
{
// Home is your controller, Index is your action name
$("#yourdiv").load("#Url.Action("Index","Home")", { 'id' : '123' },
function (response, status, xhr)
{
if (status == "error")
{
alert("An error occurred while loading the results.");
}
});
});
});
</script>
<div id="yourdiv">
</div>
Controller
public virtual ActionResult Index(string id)
{
var myModel = GetSomeData();
return Partial(myModel);
}
View
#model IEnumerable<YourObjects>
#if (Model == null || Model.Count() == 0)
{
<p>No results found</p>
}
else
{
<ul>
#foreach (YourObjects myobject in Model)
{
<li>#myObject.Name</li>
}
</ul>
}
You can do this by following these steps. In your controller, you return a partial view.
[HttpGet]
public virtual ActionResult LoadPartialViewDynamically()
{
var query = _repository.GetQuery();
return PartialView("_PartialViewName", query);
}
then in the view you have an empty div
<div id="partialgoeshere"></div>
and then load the partial view using jQuery:
function LoadPartialView() {
$.get("#Url.Action(MVC.ControllerName.LoadPartialViewDynamically())", { null }, function (data) {
$("#partialgoeshere").empty();
$("#partialgoeshere").html(data);
});
}
Hope this helps
I believe you can do something like this example, just using the change event on your dropdown instead. It's a simple jQuery call, you can find more on the jQuery website.
$("#dropdown").change(function() {
$("#destination").load("/Products/GetProduct", $(this).val(),
function(result) {
// do what you need to do
});
});
The first parameter is the view you need to call for the details.
The second parameter is the selected value.
The third parameter of the $.load function is the callback function, where you can parse the result and do what you need to do.
If you have a multiple select $(this).val() that will give you an array with the selected options.
If you want only return a Json object you may want to follow this example.
Use Ajax :)
http://api.jquery.com/jQuery.ajax/
Example:
$.post(window.gRootPath + "Customer/PartialView", { Question: questionId})
.done(function (data) {
$('#partialDiv').html(data.responceText);
});
You can use ajax to call action an then just insert html string using jQuery to the page where you want it to appear:
Server-side:
Render partial view to string
Renders partial view on server to html string, useful when you need to add partial view to ASP.NET MVC page via AJAX.
Client-side:
$('#yourDdl').change(function()
{
$.get('/InsertPartialViewUsingAjax', function (data)
{
$('#container').html(data);
});
});
The following article tells you how to do it with minimum javascript. Basically you return html instead of JSON to your response object.
https://www.simple-talk.com/content/article.aspx?article=2118
I am implementing client side validation in mvc3.
I got my form showing via jquery dialog, and submit via ajax post
I am not sure is it necessary, but i created a partial class in my Model to customize the validation:
[MetadataType(typeof (FoodMetaData))]
public partial class FOOD
{
[Bind(Exclude="FoodID")]
public class FoodMetaData
{
[ScaffoldColumn(false)]
public object FoodID { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter a name")]
public object FoodName { get; set; }
[Range(1, 200, ErrorMessage = "Please enter a valid amount")]
public object FoodAmount { get; set; }
public object StorageDate { get; set; }
public object ExpiryDate { get; set; }
Currently I only get the validation shown at the amount field if i enter a string or a number out of the range. However, If i empty the Name field, nothing happen.
This is my first try on client side validation and got no idea what is happening. Can anyone please give me some advice??
Appreciate any help, thanks...
Here's an example of how you could implement a partial form with jQuery dialog.
As always start with a view model:
public class MyViewModel
{
[Required]
public string SomeProperty { get; set; }
}
then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Edit()
{
return PartialView(new MyViewModel());
}
[HttpPost]
public ActionResult Edit(MyViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView(model);
}
// TODO: validation passed => process the model and return a JSON success
return Json(true);
}
}
and then a ~/Views/Home/Index.cshtml view which will contain only a link to the dialog:
#Html.ActionLink("click me for dialog", "edit", null, new { id = "showDialog" })
<div id="dialog"></div>
and a ~/Views/Home/Edit.cstml partial which will contain the form that we want to be shown in the dialog:
#model MyViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.SomeProperty)
#Html.EditorFor(x => x.SomeProperty)
#Html.ValidationMessageFor(x => x.SomeProperty)
<button type="submit">Save</button>
}
All that is left now is to wire up. So we import the necessary scripts:
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
and then write our own to make the dialog live:
$(function () {
$('#showDialog').click(function () {
$('#dialog').dialog().load(this.href, function (result) {
ajaxify(this);
});
return false;
});
});
function ajaxify(dialog) {
// we need to parse client validation rules
// because the form was injected into the DOM later as
// part of the dialog. It was not present initially
// See here for more info: http://weblogs.asp.net/imranbaloch/archive/2011/03/05/unobtrusive-client-side-validation-with-dynamic-contents-in-asp-net-mvc.aspx
$.validator.unobtrusive.parse($(dialog));
// AJAXify the form
$('form', dialog).submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result === true) {
// The controller action returned a JSON result
// inidicating the success
alert('thank you for submitting');
$(dialog).dialog('close');
} else {
// there was a validation error => we refresh the dialog
// and reajaxify it as we have now modified the DOM
dialog.html(result);
ajaxify(dialog);
}
}
});
return false;
});
}
Now you could adapt this to any view model you want with any editor templates and validation rules.
I just found out that jquery client side validation is only triggered after 1st form submission after i gone through the example here: http://weblogs.asp.net/imranbaloch/archive/2011/04/30/eagerly-performing-asp-net-mvc-3-unobtrusive-client-side-validation.aspx
A great one! It helps to solve my weird problem by editing the jquery.validate.unobtrusive(.min).js file by this:
options: { // options structure passed to jQuery Validate's validate() method
errorClass: "input-validation-error",
errorElement: "span",
errorPlacement: $.proxy(onError, form),
invalidHandler: $.proxy(onErrors, form),
messages: {},
rules: {},
success: $.proxy(onSuccess, form),
onfocusout: function (element) { $(element).valid(); }
}
Thanks for every help!