This is a MVC VB.NET Razor application. I have a partial view which loads in the bottom of a parent view. And in that partial view I have buttons that when click fire a popup dialog modal window which has a partial view attached to it. The user is supposed to be able to edit the form then click update and the information is then posted to the controller. However I am getting the below error message on submit.
I followed the blog here to get everything wired up. When the update button is clicked there error is occuring here:
Below is the PartialView that contains the buttons and javascript that trigger the popup modal
#ModelTYPE IEnumerable(of data_manager.attendance)
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascrip</script>
<table>
<tr>
<th>Conf. Number</th>
<th>Class Title</th>
<th>Status of Class</th>
<td>Edit</td>
</tr>
#For Each x In Model
Dim currentItem = x
#<tr>
<td>#Html.DisplayFor(Function(f) currentItem.conf_number)</td>
<td>#Html.DisplayFor(Function(f) currentItem.courseTitle)</td>
#If currentItem.Completed_Class = "Completed" Then
#<td>#Html.ActionLink("Completed(Print Cert)", "Ind_Cert", "Printing", New With {.firstName = currentItem.firstName, .lastname = currentItem.lastName, .classRef = currentItem.course_ref, .cNumber = currentItem.conf_number}, Nothing)</td>
Else
#<td>#Html.DisplayFor(Function(f) currentItem.Completed_Class)</td>
End If
<td>#Html.ActionLink("Modify", "CourseHistoryEdit", New With {.id = currentItem.id}, New With {.class = "editLink"})</td>
</tr>
Next
</table>
<div id="updateDialog" title="Update Attendance"></div>
<script type="text/javascript">
var linkObj;
$(function () {
$(".editLink").button();
$('#updateDialog').dialog({
autoOpen: false,
width: 400,
resizable: false,
modal: true,
buttons: {
"Update": function () {
$("#update-message").html(''); //make sure there is nothing on the message before we continue
$("#updateAttendance").submit();
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
$(".editLink").click(function () {
//change the title of the dialgo
linkObj = $(this);
var dialogDiv = $('#updateDialog');
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data) {
dialogDiv.html(data);
//validation
var $form = $("#updateAttendance");
// Unbind existing validation
$form.unbind();
$form.data("validator", null);
// Check document for changes
$.validator.unobtrusive.parse(document);
// Re add validation with changes
$form.validate($form.data("unobtrusiveValidation").options);
//open dialog
dialogDiv.dialog('open');
});
return false;
});
});
function updateSuccess(data) {
if (data.Success == true) {
//we update the table's info
var parent = linkObj.closest("tr");
parent.find(".Completed_Class").html(data.Object.completed);
parent.find(".carDescription").html(data.Object.Description);
//now we can close the dialog
$('#updateDialog').dialog('close');
//twitter type notification
$('#commonMessage').html("Update Complete");
$('#commonMessage').delay(400).slideDown(400).delay(3000).slideUp(400);
}
else {
$("#update-message").html(data.ErrorMessage);
$("#update-message").show();
}
}
</script>
And this is the partialView that is rendered when the Modify button is clicked next to each one.
#ModelTYPE DataModels.DataModels.AjaxCourseHistoryEdit
#Using (Ajax.BeginForm("CourseHistoryEdit", "Admin", Nothing, New AjaxOptions With {.InsertionMode = InsertionMode.Replace, .HttpMethod = "POST", .OnSuccess = "updateSuccess"}, New With {.id = "updateAttendance"}))
#Html.ValidationSummary(true)
#<fieldset>
<legend>Attendance Update</legend>
#Html.HiddenFor(Function(m) Model.attendId)
<div class="editor-label">
#Html.Label("Course Title")
</div>
<div class="editor-field">
#Html.DisplayFor(Function(m) Model.courseTitle)
</div>
<div class="editor-label">
#Html.Label("Completed Status")
</div>
<div class="editor-field">
#Html.DropDownList("completed", New SelectList(ViewBag.CourseStatuses))
</div>
<div class="editor-label">
#Html.Label("Hours Completed")
</div>
<div>
#Html.EditorFor(Function(m) Model.hoursCompleted)
</div>
</fieldset>
End Using
Below are the javascript libraries that are being loaded in the _layout file for the project.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.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>
Any help is greatly appreciated. I have went around with this for hours and google searches have turned up several SO posts saying that Unexpected token u is related to an invalid line termination. This helps me none as I cannot find anything that remotely looks like improper html namely tags that arent closed..
I had a csharper bring up the # on the table and fieldset. This is normal in these instances for vb.net below is a screenshot of the rendered html
A comment made by Moeri pointed me in the right direction. It turned out that my model was using a integer value for the hiddenFor value. Which for reasons unknown to me the AJAX post did not like that at all. By changing the type of attendId from Integer to String and further using proper editorFor / labelFor the issue has been resolved. Maybe this will help someone that hits this stumbling block as I have.
Related
I have the following line of code which uses html helper's PagedListPager:
#Html.PagedListPager(Model.kyc_paged_list, page => Url.Action("ClientDetails", new { id = ViewBag.ID, kyc_page = page, transaction_page = Model.transaction_page, active = "kyc" }))
When clicking on the the pager the entire page reloads. But I only want the table with id="kyc-history" to refresh.
I know how to reload the table using a JavaScript function but I don't know how to call it from the PagedListPager.
Any ideas how I can call it? Let's say that the JS function is called reloadTable()
I was having the same problem and this article (done by Anders Lybecker) helped me out and now everything working!
It's very clear with steps, But make sure to make backup before starting!
Take a look:
AJAX paging for ASP.NET MVC sites
In summary you make 2 Action Results in your Controler with 2 Views 1 for your page (in my case it's Index View) the other for the List that contain the PagedListPager control (List View). And put the list View inside the Index View. And write the JQuery code for the PagedListPager in the Index View.
You can read the article for the details!
And this is my code with a little extra things I noticed to help you more:
The List View:
#model IPagedList<StudentRegSys.Models.Student>
#{
Layout = null;
}
#using PagedList.Mvc;
#using PagedList;
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400italic,400,600,700" rel="stylesheet">
#Styles.Render("~/template/css")
<div class="container">
<div class="row">
<!-- The List Code-->
<div class="pagination-control">
#Html.PagedListPager(Model, i => Url.Action("List", "Home", new { i, search = Request.QueryString["search"] }))
</div>
</div>
</div>
#Scripts.Render("~/template/js")
Note: Make sure to make Layout = null; and put the Styles Links & the Scripts manual in this View to avoid design issues.
In the Controller: (it's Home Controller in my case)
// GET: /Home/Index
public ViewResult Index()
{
return View();
}
// GET: /Home/List
public ActionResult List(int? i, string search = "")
{
try
{
var students = _context.Student.Include(s => s.Major)
.OrderBy(s => s.Name)
.Where(s => s.Name.Contains(search) || s.Major.Name.Contains(search) ||
s.Address.Contains(search) || s.Phone.Contains(search))
.ToList().ToPagedList(i ?? 1, 8);
return View(students);
}
catch (Exception)
{
return HttpNotFound();
}
}
The Index View:
#{
ViewBag.title = "Home";
}
<section id="intro">
<!-- Some Code -->
</section>
<section id="maincontent">
#Html.Action("List") <!-- to call the List view -->
</section>
<script>
$(document).ready(function () {
$(document).on("click", ".pagination-control a[href]", function () {
$.ajax({
url: $(this).attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#maincontent').html(result);
}
});
return false;
});
});
</script>
Note: Make sure to put the html(result) in the root container of the list in my case was <section id="maincontent">.
Hope this help you out :)
i've bought the latest ContentBuilder.js from innovastudio.
I've integrated it in my cms and is working fine.
Now i have created new static blocks this works fine also.
But now i try to make dynamic blocks with php data passed from the controller when the page loads but can't seems to make it work.
I know php loads before javascript .But i'm a little bit stuck.
Does someone already have worked with contentbuilder.js and could someone please guide me how to resolve this issue please?
I'm working in laravel 5.8 , i did getelementbyid with javascript and replace the value with the dynamic value .
This works but only for single rows and not collections.-
<script type="text/javascript">
jQuery(document).ready(function ($) {
var DBaddress = '{{$settings[0]['address']}}';
var DBnumber = '{{$settings[0]['number']}}';
var DBpostalcode = '{{$settings[0]['postal_code']}}';
var DBtown = '{{$settings[0]['town']}}';
var DBtel = '{{$settings[0]['telephone']}}';
var DBemail = '{{$settings[0]['email']}}';
var obj = $.contentbuilder({
container: '.container_edit',
imageselect: 'admin/laravel-filemanager',
cellFormat: '<div class="col-md-12"></div>',
rowFormat: '<div class="row"></div>',
framework: 'bootstrap',
});
$('#btnViewSnippets').on('click', function () {
obj.viewSnippets();
});
$('#btnViewHtml').on('click', function () {
obj.viewHtml();
});
/*$('#btnSave').on('click', function () {
save(obj.html());
});*/
document.getElementById("address").innerHTML= DBaddress;
document.getElementById("number").innerHTML= DBnumber;
document.getElementById("postalcode").innerHTML= DBpostalcode;
document.getElementById("town").innerHTML= DBtown;
document.getElementById("tel").innerHTML= DBtel;
document.getElementById("email").innerHTML= DBemail;
});
</script>
Here the section where the page builder is set :
#section('content')
<div class="container_edit">
{!! $page->contentBuilder !!}
</div>
#if( basename(url()->current()) !== $page->slug)
<div class="is-tool" style="position:fixed;width:210px;height:50px;border:none;top:250px;bottom:50px;left:auto;right:30px;text-align:right;display:block">
<button id="btnViewSnippets" class="classic" style="width:70px;height:50px;">+ Add</button>
<button id="btnViewHtml" class="classic" style="width:70px;height:50px;">HTML</button>
<button id="btnSave" data-id="{{$editPageDetails[0]->uuid}}" class="classic" style="width:70px;height:50px;">SAVE</button>
</div>
#endif
#endsection
This is how i could manage to make it work, but again this is for single rows. I would like to have the complete collection so i could create dynamic blocks
Iam learning Backbone js and so I have started creating sample application.
BTW, iam facing one problem now ie., model is saving more than once in my database. I mean when you click 'Create User' , you'll see a form, so when I click that 'Create User' button, details are getting saved more than once in my DB and so all duplicate users info displayed in the home page.
Actually iam trying to practice this video: https://www.youtube.com/watch?v=FZSjvWtUxYk
The output would look like this: http://backbonetutorials.com/videos/beginner/#/new
Here is my Code:
<html>
<head>
<link rel="stylesheet"
href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.1/css/bootstrap.min.css">
<script type="text/javascript">
/*$.getJSON('api/users/1',function(data){
console.log(data);
});*/
</script>
</head>
<body>
<div class="container">
<h1> User Manager</h1>
<hr/>
<div class="page"></div>
</div>
<script type="text/template" id="user-list-template">
New User
<hr/>
<table class="table stripped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<% _.each(users, function(user){ %>
<tr>
<td><%= user.get('firstName') %></td>
<td><%= user.get('lastName') %></td>
<td><%= user.get('age') %></td>
</tr>
<% }); %>
</tbody>
</table>
</script>
<script type="text/template" id="add-user-template">
<legend>Create User</legend>
<form class="add-user-form">
First Name <input type="text" id="firstName"/><br/>
Last Name <input type="text" id="lastName"/><br/>
Age <input type="text" id="age"/><hr/>
<input type="submit" value="Create User">
</form>
</script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script type="text/javascript">
var UsersList = Backbone.Collection.extend({
url: 'api/users'
});
var User = Backbone.Model.extend({
urlRoot: 'api/users'
});
var UsersListView = Backbone.View.extend({
el: '.page',
render: function(){
var that = this;
var users = new UsersList();
users.fetch({
success: function(usersList){
var template = _.template($('#user-list-template').html())({users: usersList.models});
that.$el.html(template);
}
});
}
});
var AddUserView = Backbone.View.extend({
el: '.page',
render: function(){
var template = _.template($('#add-user-template').html())({user:null});
this.$el.html(template);
},
events: {
'submit .add-user-form': 'saveOrUpdateUser'
},
saveOrUpdateUser: function(e){
e.preventDefault();
var userDetails = {firstName: $('#firstName').val(), lastName: $('#lastName').val(), age: $('#age').val()};
var user = new User();
user.save(userDetails,{ //SEEMS LIKE HERE HAVING SOME PROBLEM
success: function(){
console.log('INSIDE SUCCESS..');
router.navigate('',{trigger: 'true'});
}
});
}
});
var Router = Backbone.Router.extend({
routes:{
'':'home',
'new':'addUser'
}
});
var router = new Router();
router.on('route:home',function(){
var usersListView = new UsersListView();
usersListView.render();
});
router.on('route:addUser',function(){
var addUserView = new AddUserView();
addUserView.render();
});
Backbone.history.start();
</script>
</body>
</html>
Please suggest me what went wrong and how to fix this?
#MarciaYudkin you'll notice that when you first load your site and create a user, that first user does not save a duplicate. However, the next time you fill out a CreateUser form, the user will get saved twice. What's happening here is that you are suffering from Zombie Views! (Ahh!)
A Zombie View is a view that you thought went away, but in fact remains in the background. Since they're still alive, they are also still bound its view events. The zombie view you detected in your code is:
router.on('route:addUser',function(){
var addUserView = new AddUserView(); // <---Right here!
addUserView.render();
});
Every time a user follows the route:addUser route they end up creating a new AddUserView. This view renders itself and attaches itself to the DOM. You would think that since you "removed" your old view from the DOM, it would simply disappear, right? Well, it does---from the DOM---but not from memory! Since that view still has event bound to the DOM, it does not get garbage collection. When a DOM element that was bound to any previous views is triggered (like by clicking it), the current, as well as all the old, undisposed, views are still bound to it, and all of them respond to the trigger. That's what's happening to you. Here, see this fiddle I cooked up.
How to fix it
The way out of this is to keep a reference to the view around, so that you could properly dispose of it. So, for example, you could attach a reference to the view in your router, and do,
router.on('route:addUser',function(){
// If the view exists, remove it
if (router.addUserView) {
router.addUserView.remove();
router.addUserView.off();
}
router.addUserView = new AddUserView();
router.addUserView.render();
});
Here we call Backbone.View.remove(), which really does this.$el.remove() behind the scences, effectively removing the DOM elements referred to by our view and releasing the bound events. Now our view can be garbage collected!
You can see how I answered this question recently for another angle on this: Saving User Data more than once. And I think I'd be remiss if I didn't include Derick Bailey's seminal article on zombie views (from where I got most of my information), Zombies! RUN! (Managing Page Transitions In Backbone Apps)
My problem is when page is loaded first time,alert(1) and alert(2) pops up, but when I click on my save button alert(3) don't pops up but validation message is shown(doesn't meter if I fill correct or wrong my dropdownlist)and everything is saved.
I have this kind of JS:
<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>
<script type="text/javascript">
$(document).ready(function () {
alert(1);
PassWayValidators();
$('#documents_TravelDocumentDocumentPass_PassDate').datepicker();
});
function PassWayValidators() {
alert(2);
$.validator.addMethod('PassWayValidator',
function (value, element) {
alert(3);
}, 'Please Inert Valid Numbers');
$("#documents_TravelDocumentDocumentPass_PassWayId").rules("add", {
PassWayValidator: true
});
}
</script>
<...Some Code Here...>
<div class="TravelDocumentDocumentPassCommentInner">
<span>გადაცემის ფორმა
<br />
#Html.DropDownListFor(model => documents.TravelDocumentDocumentPass.PassWayId, (IEnumerable<SelectListItem>)ViewBag.DocumentPassTypeList, String.Empty, isDisabled)
#Html.ValidationMessageFor(model => documents.TravelDocumentDocumentPass.PassWayId, "*")
</span>
</div>
<...Some Code Here too... and>
#Html.ValidationSummary()
Can anyone tell me what is the problem ?
Since you're writing a custom validator, I see two things right off the bat that needs to be corrected.
First, you need to call PassWayValidators(); outside of $(document).ready(). I'm not 100% sure that it is necessary, but I think that is the only way I was able to get custom validation to work.
PassWayValidators();
$(document).ready(function () {
$('#documents_TravelDocumentDocumentPass_PassDate').datepicker();
});
Then, you need to configure your dropdown to make sure it calls your validation function with by specifying certain html attributes.
#Html.DropDownListFor(model =>
documents.TravelDocumentDocumentPass.PassWayId,
(IEnumerable<SelectListItem>)ViewBag.DocumentPassTypeList,
String.Empty,
new {
data_val = "true",
data_val_PassWayValidator = "Please insert valid numbers"
})
Something like that. I don't know what rules("add" { }) is for, but I'm not sure if you need that. In case I missed something, here is a complete sample taken from one of my applications.
<!-- some form and other html and stuff -->
#Html.TextBox("Amount", null, new
{
data_val = "true",
data_val_required = "This field is required",
data_val_number = "The field must be a number",
data_val_notBeZero = "Value must not be zero"
})
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
<script type="text/javascript">
// validators
$.validator.addMethod("notBeZero", function (value, element)
{
if (Number(Math.abs(value).toFixed(2)) == 0)
{
return false;
}
return true;
}, "Value must not be zero");
$.validator.unobtrusive.adapters.addBool("notBeZero");
</script>
This is in ASP.NET. We are using a ExtJS frontend, and have our own VB.NET controls to make all the Ext Forms and stuff. However, I hope this can be done in plain javascript. There is already some Javascript on the page for the 'Test Connection' button click and handling the result.
However, I need validation on the screen to make sure that a user tests the connection BEFORE saving the screen. (Hits the test button before hitting the save button) -- EACH time they visit the screen.
Here is the code for the page:
<%# Page Language="VB" Inherits="Core.Web.EditBaseView" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script language="javascript" type="text/javascript">
function testConnection() {
Global.mask('Testing Connection...');
KBBConnectorController.TestConnection(function(result) { testConnectionCallback(result) });
}
function testConnectionCallback(result) {
Global.unmask();
if (result.Data.Result) {
Global.alert("Connection to KBB Successful.");
}
else {
Global.alertError(result.Data.Messages[0].Text, result.Data.ExceptionId);
}
}
function Validate() {
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div style="display:none">
<% =Html.DropDownList("ddlMarketValues", TryCast(Model.MarketValues, SelectList))%>
</div>
<div>
<%
Using KBBForm As New WebControls.Forms.Form
With KBBForm
.OnValidate = "Validate"
.ID = "KBB"
.ItemName = "connector"
With .Toolbar
.UseDefaultButtons = False
.AddButton(Forms.FormToolbar.ButtonType.Save)
.AddButton(Forms.FormToolbar.ButtonType.Cancel)
.AddButton("Test Connection", "testConnection", "icon-button-testconnection", , "Test connectione")
End With
With .CenterRegion
.Id = "centerRegion"
With .AddFieldSet("Activate Service")
.Id = "activate"
.LabelWidth = 0
Dim cb As New Forms.Control("IsActive", "", "", Model.IsActive, Forms.Control.ControlType.CheckBox)
cb.BoxLabel = "Activate Service"
.AddControl(cb)
End With
With .AddFieldSet("Connection Parameters")
.Id = "params"
.LabelWidth = 150
.AddControl(New Forms.Control("UserName", "", "User Name", Model.UserName, Forms.Control.ControlType.TextField))
.AddControl(New Forms.Control("Password", "", "Password", Model.Password, Forms.Control.ControlType.Password))
.AddControl(New Forms.Control("LoginUrl", "", "URL", Model.LoginUrl))
With .AddControl(New Forms.Control("ddlMarketValues", "", "Market Value", , Forms.Control.ControlType.ComboBox))
.Id = "ddlMarketValues"
End With
End With
End With
Response.Write(.ToString)
End With
End Using
%>
</div>
</form>
</body>
</html>
As you can see I put an OnValidate function in there but it's blank, and you can see that it's tied to the Form as well. I tried fooling around with that but I could only put something together that would ask me to test every single time I clicked Save, and it wouldn't know if I already tested or not.
Any help? Thanks ahead of time.
-Scott
Uh, this should work if I did understand you correctly.
In the code which handles the result of the connection test, set a flag that indicates that the connection has been tested.
In the handler of the Save button check for that flag, and if it's not set display a message of some kind instead of actually performing the saving operation.
Your flag could be global variable which is initially set to false this way the user would be required to run the test each time the visit the page.
As on how you would override/intercept the Save buttons handler... uh... guess you'll have to extend the VB stuff for that.
Why not just hide the save button until the test connection is pressed and the connection works?