How to execute JavaScript function on PartialView load in MVC 3 - javascript

\\code
public ActionResult mapPartial(DataTable dt)
{
string strEvents = "[";
foreach (DataRow row in dt.Rows)
{
strEvents += "[" + row["Lat"].ToString() + ", " + row["Long"].ToString() + ", " + "\"" +
row["LastName"].ToString() + row["DateOfBirth"].ToString() + "\"" + "],";
}
strEvents = strEvents.Remove(strEvents.LastIndexOf(","));
strEvents += "]";
ViewBag.locpoints = strEvents;
return PartialView(dt);
}
//in the partial view page
<script type="text/javascript">
function mapInit(Viewbag.locpoints) {
var arr = $.parseJSON(Viewbag.locpoints);
//more code which assigns a map to div map below
}
</script>
<div id="map" class="map"></div>
How can i call the JS function immediately to render my map when the partial view is loaded. The partial method in the controller returns a string which is used as parameter in the JS function. Hope it makes sense.

Since you appear to be using JQuery why not:
<script type="text/javascript">
$(document).ready(function(){
var arr = $.parseJSON("#Viewbag.locpoints");
//more code which assigns a map to div map below
});
</script>
I also changed how you referenced your ViewBag value since the way you have it, it won't be be a string literal in JavaScript.
Also, as a side note consider using JSON serializer to convert your data into JSON. It is considered a bad practice to do it manually like you did above.

After you define it, you just call it. However, it looks like you are including the MVC Viewbag values in the JS function definition. You should be passing those values when you call the JS method:
<script type="text/javascript">
function mapInit(locPoints) {
var arr = $.parseJSON(locPoints);
//more code which assigns a map to div map below
}
mapInit(#(Viewbag.locpoints));
</script>
Note: This assumes you have jQuery loaded.

Consider using the onSuccess Ajax Option and wire up a javascript function where your jquery is written. For example you have following script written in your mainView that calls the partial View. Suppose you want do something when the anchor tag in your partial view is clicked
var fromPartial=function()
{
var v = $(this).closest("div");
var mId = v.attr('id');
if (mId == 'divDetail') {
event.preventDefault();
//what you want to achieve
}
}
Now in your partial view the anchor tag is created as shown below
#Ajax.ActionLink("Select", "AssignSpeaker", new {
conferenceId = ViewBag.ConferenceId, sessionId = session.Id },
new AjaxOptions() { HttpMethod="Get",
InsertionMode= InsertionMode.Replace, UpdateTargetId="yourTarget",
OnSuccess="fromPartial" })

We have implemented a much simpler solution.
_Layout.cshtml after #RenderSection("scripts", required: false) (and Jquery,etc.)
<script>
$(document).ready(function () { if (typeof partialScript !== "undefined") partialScript();});
</script>
Then, in your partial view:
<script type="text/javascript">
function partialScript() {
alert("hi");
}
</script>
This ensures the following:
jQuery is loaded
All main view scripts are loaded
DOM is ready

Try to call your controller via JQuery.
$(document).ready(function () {
$.ajax({
type: 'GET',
url: 'your_controller_url',
success: function (data) {
//Do your stuffs here
}
});
}

The only way you can do this is by calling your controller action using JQuery and have it return your partial view. Use Jquery to update whatever section of the page the partial view goes to and then call the javascript method you want to render the map

Related

Trying to populate an html option list with jQuery's get method

I currently have a servlet setup to send over a list of our active servers. The method grabs the servlet data, processes it, then injects the html into the datalist tag. HTML injection process works, but when I'm splitting the array by the concat separator (which I've done before), I get no values. Below I'll explain with code examples:
HTML:
<label for="server_id_text">Server ID: </label>
<input id="server_id_text" list="server_names" name="server_id" required>
<datalist id="server_names">
<!--This gets injected with the active servers grabbed through a get request-->
</datalist>
Javascript connecting to server to get data:
Note: serverList is a global variable.
var serverList = "";
function setupAutoComplete() {
$.get(baseURL + "/SupportPortal", function (data, status) {
console.debug("Status with auto comp id: " + status);
serverList = data;
console.debug("server list auto comp at post mailing: " + serverList);
});
}
This method is called in the function that is called when the onload event is called in the body tag
Here are the two methods that inject the html:
function setupServerName() {
document.getElementById("server_names").innerHTML = getServerListHTML();
}
function getServerListHTML(){
console.debug("Autocomplete process running...");
var servArr = String(serverList).split('*');
var html = '';
var temp = '<option value="{serverName}">';
console.debug("Array:" + servArr.toString());
if (serverList == 'undefined' || servArr.length == 0){
console.debug("serverList is empty...");
return '';
}
for (var i =0; i < servArr.length; ++i){
html += temp.replace("{serverName}", servArr[i]);
}
console.debug("html: " + html);
console.debug("ServList size " + servArr.length);
return html;
}
When the page loads, setupAutoCompelte() is called first. Then, setupServerName() is called.
My issue is that after I load the page, I get the correct response from the server. For instance, I'll get server1*server2 as a response to the jQuery $.get(...) call. Then I go to split the string into an array, and I get back an empty html tag (<option value="">);
Also, the debug console info are as follows:
Autocomplete process running...
Array:
html: <option value="">
ServList size 1
Status with auto comp id: success
server list auto comp at post mailing: server1*server2
Thanks for the help!
I believe that your setupServerName() function is being called before the AJAX request in setupAutoComplete() returns, so your serverList is an empty string at that point. What you need to do is populate your <datalist> from inside your AJAX callback in setupAutoComplete().
// setup autocomplete datalist
function setupAutoComplete() {
var $datalist = $('#server_names');
$.get(baseURL + '/SupportPortal').then(function (data) {
// update datalist
if (!data || !data.length) {
// no servers, empty list
$datalist.html('');
} else {
// create options html:
// reduce array of server names
// to HTML string, and set as
// innerHTML of the dataset
$datalist.html(data.split('*').reduce(function (html, server) {
return html + '<option value="' + server + '">\n';
},''));
}
});
}
// on page load, setup autocomplete
$(function () {
setupAutoComplete();
});
As you can see from "debug console info":
the get function is asyncrhonous so you need to change your setupAutoComplete get part to:
$.get(baseURL + "/SupportPortal", function (data, status) {
console.debug("Status with auto comp id: " + status);
serverList = data;
setupServerName();
console.debug("server list auto comp at post mailing: " + serverList);
});
On page load try to call directly the setupServerName function within the success event of get function. A different approach is to divide the setupServerName function so that the part related to the serverList variable becomes part of another function.
The serverList variable is global but its content is filled after the setupServerName is executed.

How to keep Web Essential regions from breaking jquery?

I'm using Web Essentials 2012 and Visual Studio 2012 and Razor Web Pages (not MVC).
I have a jquery ajax that looks like this:
$("#test1").ready(function () {
var test = { "loadTestList": "loadTestList" };
function loadTestList(response) {
var ddlTest = $('#test1');
ddlTest.empty();
ddlTest.append(
$("<option></option>").text('All').val('All')
);
for (var i = 0; i < response.length; ++i) {
ddlTest.append(
$("<option></option>").text(response[i].TestName).val(response[i].TestName)
);
}
}
$.ajax({
url: "../Controllers/TestController.cshtml",
data: test,
type: "POST",
dataType: "json",
success: function (response) {
loadTestList(response);
},
error: function () {
console.log("Sorry, there seems to be a problem contacting the Test server.");
console.log(response.responseStatus);
console.log(response.responseText);
}
});
});
This actually works.
Now I have my controller has code like this:
#* Controllers/TestController.cshtml *#
#{
if (IsPost && Request["loadTestList"] != null)
{
var tests = new TestRepository(new TestContext());
var testslist = tests.Load();
Json.Write(testslist, Response.Output);
}
}#
And yes, this works too.
But when I do this:
#{
<!-- #region TestMe -->
if (IsPost && Request["loadTestList"] != null)
{
var tests = new TestRepository(new TestContext());
var testslist = tests.Load();
Json.Write(testslist, Response.Output);
}
<!-- #endregion -->
}#
This breaks jQuery every time. $.ajax goes to error everytime.
So does anyone know a way to prevent this from happening? I really like regions, but I can't have it breaking the rest of jQuery.
Also why would this break jQuery in the first place if all I'm passing (through Json.Write) is testslist?
NOTE: TestController.cshtml has only server side code. No HTML at all.
Inside #{ } block you can use standard c# precompiler directive:
#region [region_name]
#endregion
Inside
<script></script>
block use web essentials pattern for javaScript:
//#region [region_name]
//#endregion

ASP WebForms re-evaluate property on post back

Basically I want to set the default date on a jQuery calendar. I have a little script that runs fine when the page loads.
<script type="text/javascript">
$(function () {
var calendarPicker = $('input[name="ctl00$MainContent$ucDetails$LeftPanel$fieldDate$dateValue$calendarPicker"]');
if (calendarPicker.val() == "") {
calendarPicker.datepicker("option", "defaultDate", '<%# CalendarDefaultDate %>');
}
});
</script>
However, when the user changes the value on a combo box, the page posts back and runs some code which causes the value of CalendarDefaultDate to update. The problem is that even though the value of the property has changed, it doesn't get reflected on the page.
Any ideas how to fix this? Many thanks.
Update 1. Tried using the ClientScriptManager as advised. (with no joy)
StringBuilder builder = new StringBuilder();
builder.AppendLine("$(function(){var calendarPicker = $(\"input[name='ctl00$MainContent$ucDetails$LeftPanel$fieldDate$dateValue$calendarPicker']\")");
builder.AppendLine("if (calendarPicker.val() == '') {");
builder.AppendLine("calendarPicker.datepicker(\"option\", \"defaultDate\", '" + CalendarDefaultDate + "')");
builder.AppendLine("}});");
Page.ClientScript.RegisterStartupScript(GetType(), "CalenderDefaultDate", builder.ToString(), true);
You can use the ClientScriptManager to run your function on the reload:
ClientScriptManager.RegisterStartupScript(this.GetType(), "AKey", "MyFunction();", true);
http://msdn.microsoft.com/en-us/library/asz8zsxy.aspx
Try to declare your function on aspx file this way.
<script type="text/javascript">
function assignCalendar () {
var calendarPicker = $('input[name="ctl00$MainContent$ucDetails$LeftPanel$fieldDate$dateValue$calendarPicker"]');
if (calendarPicker.val() == "") {
calendarPicker.datepicker("option", "defaultDate", '<%# CalendarDefaultDate %>');
}
};
</script>
Then in code behind call it like below:
ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "assignCalendar ", "<script type='text/javascript'>assignCalendar();</script>", false);
If you put it on PageLoad event i think it will work

Call MVC action method by javascript but not using AJAX

I have a MVC3 action method with 3 parameters like this:
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
and I want to call this by normal javascript function not AJAX (because it's not necessary to use AJAX function)
I tried to use this function but it didn't work:
window.location.assign(url);
It didn't jump to Insert action of QuestionController.
Is there someone would like to help me? Thanks a lot
This is more detail
I want to insert new Question to database, but I must get data from CKeditor, so I have to use this function below to get and validate data
// insert new question
$("#btnDangCauHoi").click(function () {
//validate input data
//chủ đề câu hỏi
var title = $("#txtTitle").val();
if (title == "") {
alert("bạn chưa nhập chủ đề câu hỏi");
return;
}
//nội dung câu hỏi
var content = GetContents();
content = "xyz";
if (content == "") {
alert("bạn chưa nhập nội dung câu hỏi");
return;
}
//danh sách Tag
var listTags = new Array();
var Tags = $("#list_tag").children();
if (Tags.length == 0) {
alert("bạn chưa chọn tag cho câu hỏi");
return;
}
for (var i = 0; i < Tags.length; i++) {
var id = Tags[i].id;
listTags[i] = id;
//var e = listTags[i];
}
var data = {
"_strTitle": title,
"_strContent": content,
"_listTags": listTags.toString()
};
// $.post(url, data, function (result) {
// alert(result);
// });
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
window.location.assign(url); // I try to use this, and window.location also but they're not working
});
This URL call MVC action "Insert" below by POST method
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(string _strTitle, string _strContent, string _listTags)
{
try
{
//some code here
}
catch(Exception ex)
{
//if some error come up
ViewBag.Message = ex.Message;
return View("Error");
}
// if insert new question success
return RedirectToAction("Index","Question");
}
If insert action success, it will redirect to index page where listing all question include new question is already inserted. If not, it will show error page. So, that's reason I don't use AJAX
Is there some one help me? Thanks :)
Try:
window.location = yourUrl;
Also, try and use Fiddler or some other similar tool to see whether the redirection takes place.
EDIT:
You action is expecting an HTTP POST method, but using window.location will cause GET method. That is the reason why your action is never called.
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(string _strTitle, string _strContent, string _listTags)
{
// Your code
}
Either change to HttpGet (which you should not) or use jQuery or other library that support Ajax in order to perform POST. You should not use GET method to update data. It will cause so many security problems for your that you would not know where to start with when tackling the problem.
Considering that you are already using jQuery, you might as well go all the way and use Ajax. Use $.post() method to perform HTTP POST operation.
Inside a callback function of the $.post() you can return false at the end in order to prevent redirection to Error or Index views.
$.post("your_url", function() {
// Do something
return false; // prevents redirection
});
That's about it.
You could try changing
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
to
var url = "/Question/Insert?_strTitle=" + title + "&_strContent=" + content + "&_listTags=" + listTags.toString();
I've removed the single quotes as they're not required.
Without seeing your php code though it's not easy to work out where the problem is.
When you say "It didn't jump to Insert action of QuestionController." do you mean that the browser didn't load that page or that when the url was loaded it didn't route to the expected controller/action?
You could use an iframe if you want to avoid using AJAX, but I would recommend using AJAX
<iframe src="" id="loader"></iframe>
<script>
document.getElementById("loader").src = url;
</script>

How to use a server side variable in javascript with Razor

I have a piece of code in a view as
#if (Model.Count() > 0)
{
var locations = new List<string>();
var count = 1;
foreach (var shop in Model)
{
locations.Add(string.Format(
#"{{
title: ""Shop Name: {0}"",
position: new google.maps.LatLng({1}, {2}),
icon: ""{3}""
}}",
shop.ShopName,
shop.Location.Latitude,
shop.Location.Longitude,
count
)
);
count++;
}
var locationsJson = "[" + string.Join(",", locations.ToArray()) + "]";
}
How can I assign the locationsJson to a javascript variable as
<script type="text/javascript">
var jsLocations = #locationsJson;
</script>
Perform your embedded server code ON the server side instead, and then you could make it a property of the model and do something like:
<script type="text/javascript">
var jsLocations = #Model.locationsJson;
</script>
I have a piece of code in a view as
You absolutely should never have such piece of code in your view. Try this (shorter, better, safer):
<script type="text/javascript">
var jsLocations = #Html.Raw(Json.Encode(Model));
$.each(jsLocations, function(index, item) {
// TODO: do something with the item, for example
// alert(item.ShopName); or alert(Location.Latitude);
});
</script>
Your code will work fine.
However, you need to escape the values in your JSON, or you'll have an XSS hole.
You should use a real JSON serializer.

Categories

Resources