I am implementing a simple JQuery autocomplete with few entries so I don't need to use a web method. The code is like this:
$( function() {
var availableTags = [
"ActionScript",
"AppleScript"
];
$( "#tags" ).autocomplete({
source: availableTags
});
} );
The entries availableTags are unique to the user so they need to come from the server. How should I get the entries from the server side to the JavaScript in ASP.NET Core?
This assumes you have some service IUserTagService like this, registered through dependency injection:
public interface IUserTagService
{
IList<string> GetUserTags();
}
Since you don’t want (or need) an AJAX call here to load the tags after the page has been rendered, we’re just going to render the tags directly into the output. For that, we basically convert the returned list from the GetUserTags method into JSON and put this into a script tag. So the end result will look mostly like your static example.
So in the .cshtml view, we first inject our service. We can use the #inject directive at the beginning of the file for this:
#inject IUserTagService userTagService;
Then, we simply open a script tag and write the output into a variable:
<script>
$(function() {
var availableTags = #Json.Serialize(userTagService.GetUserTags());
$("#tags").autocomplete({
source: availableTags
});
});
</script>
This uses the Json.Serialize which is a utility function that is available in views to serialize the list into JSON.
You can make an ajax call to your server action method which returns the list as JSON array.
$(function () {
$.getJSON("#Url.Action("GetItems")", function (availableTags) {
$( "#tags" ).autocomplete({
source: availableTags
});
});
})
Assuming your GetItems action method returns the list of items as json array
public JsonResult GetItems()
{
var list = new List<string>() {"ActionScript","AppleScript"};
return new JsonResult(list);
}
Another option is to load the data (list of strings to your main views GET action method and in the razor view, convert that to a JS Array
So in your GET action,
var list = new List<string>() {"ActionScript","AppleScript"};
ViewBag.Items = list;
return View();
and in the razor view,
#section Scripts
{
<script>
$(function() {
var availableTags = #Html.Raw(Newtonsoft.Json.JsonConvert
.SerializeObject(ViewBag.Items));
$( "#tags" ).autocomplete({
source: availableTags
});
});
</script>
}
Dependency injection is possible in asp.net core views now. poke's answer above uses that. You may consider doing that instead of the ViewBag solution above.
Related
I am using following code and it always picks up hard coded data defined in availableTags. If I dynamically load data from C# WebApi, it still picks up old data i.e. ActionScript and AppleScript.
As you can see I am printing Before and After values and they both are working correctly i.e. as I can see it assigns new data to availableTags but autocomplete still works on old data. Is there a limit on how many items can I define in availableTags? Because dynamically it is getting 504 items from my code so may be this is the issue?
What am I doing wrong?
<input id="tags">
<script>
var availableTags =
[
"ActionScript",
"AppleScript"
];
$("#tags").autocomplete
({
source: availableTags
});
$.getJSON("MyController/GetAllTags")
.done(function (data)
{
alert("Before="+ availableTags);
availableTags = data;
alert("After="+ availableTags);
});
</script>
Try this
<input id="tags">
<script>
var availableTags =
[
"ActionScript",
"AppleScript"
];
$("#tags").autocomplete
({
source: availableTags
});
$.getJSON("MyController/GetAllTags")
.done(function (data)
{
$("#tag").autocomplete('option', 'source', data)
});
</script>
Edit 1: Updating Code
I would like to pass an id parameter from this action in controller
public IActionResult BuildingDetail(int id)
{
return PartialView("_BuildingDetailsPartial", _buildingRepository.GetById(id));
}
into this load method in view to run AJAX.
#section Scripts{
<script type="text/javascript">
$(document).ready(function () {
$("#LoadBuildingDetail").click(function () {
$("#BuildingDetail").load("/employees/buildingdetail/id");
});
})
</script>}
I am new to jQuery, but I guess I need to store id vaule somehow before passing it into load function, so controller/action/parameter approach does not work. But atm I had no luck.
If you want to pass id to the controller via jquery load method, you can pass it directly into the load method as an object.
I assume you have the id's value somewhere on the page or you are hardcoding it in the view using razor syntax from your model.
In any case, try using something like this in your jquery
//passing id's value from the control on the page
$("#BuildingDetail").load("/employees/buildingdetail", { id: $("#Id").val() });
or
//passing id's value from the Model property
$("#BuildingDetail").load("/employees/buildingdetail", { id: #Model.Id });
Reference: jQuery load method
I am coding a MVC 5 internet application and would like to know how to pass values from a ViewModel into a jQuery function where I have a list of data to pass.
Usually, I would create a hidden field in the MVC View code, and then retrieve this value in the jQuery code. However, in this situation, there is not just one value from the ViewModel, but a List of objects, where each object has many values.
My ViewModel has a List<MapMarker>, where each MapMarker has the following attributes:
latitude
longitude
title
draggable
This is the jQuery function that I need to call for each MapMarker object:
function LoadMapMarker(latitude, longitude, title, draggable)
How can I call the LoadMapMarker function, with data from each of the MapMarker objects in the ViewModel list?
Thanks in advance
You can serialize your list and storage it in a hidden field. Then call LoadMapMarker by means of Javascript on client side.
Server:
using System.Web.Script.Serialization;
var MapMarkers = new List<MapMarker>();
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(MapMarkers);
return View(new MyViewModel({JsonList = json }));
View:
<input type="hidden" id= "MyHiddenFieldForMapMarker" value="#Model.JsonList" >
Client:
var MapMarkers = $("#MyHiddenFieldForMapMarker").val();
for (var MapMarker in MapMarkers) {
LoadMapMarker(MapMarker["latitude"],
MapMarker["longitude"],
MapMarker["title"],
MapMarker["draggable"]);
}
You can serialize to JSON and then store in a hidden field, or as a Javascript object like :
myJsonData= [{"id":"15aea3fa","firstname":"John","lastname":"Doe"}];
Alternatively, you can retrieve the data via an ajax call.
If you don't want to use JSON and use the data you have on your page you can do this:
You can add class (or some other attribute, for me it is easier to use classes, but it is better "programming" to use another attribute)
#foreach ()...
{
<div class="main_Marker">
<input ... class="lat"/> //using the #Model render ofc...
<input ... class="long"/>
</div>
}
Then jQuery:
$("main_Marker").each(function(index, item)) {
var lat = $(item).child(".lat");
.
.
LoadMapMarker(lat, long....);
}
If your jQuery function is present in a view, use #Html.Raw(Json.Encode(Model.JSonData)) like this
//JavaScript or jQuery function
function javascriptFunction()
{
var data = #Html.Raw(Json.Encode(Model.JSonData))
}
In the above code, JSonData is the name of the collection variable that contains data from model. In your case a List.
If your jQuery function is in a separate JavaScript file, then an AJAX request can be used to get the data from model
Controller Code
public ActionResult GetData()
{
//Your logic to get data from model
//Here data is the variable that holds the collection List<MapMarker>
return Json(data);
}
JavaScript Code for AJAX Request
function myJavaScriptFunction()
{
$.ajax({
url: '/GetData',
type: 'post',
success: function (data) {
alert("data retrieved successfully");
},
error: function () {
alert("Error retrieving data");
}
});
}
Is it possible to run jQuery from a MVC C# controller?
if (ModelState.IsValid){
//lots of C# asp.net code here
jqueryFunctionName();
}
It's important that there is a check somehow before the jQuery runs
Perhaps i can do it straight from jQuery itself, but i'm not sure how to check it?
The idea is Form -> Submit -> SOMETHING checks if valid -> if yes then wait graphic -> 2 seconds pauze -> redirect to "thanks.cshtml"
In your controller's action:
var vm = new YourViewModelTypeWithPropertyIsValid();
vm.IsValid = ModelState.IsValid;
return View(vm);
In your view:
#model YourViewModelTypeWithPropertyIsValid
<script type="text/javascript">
var isModelValid = #Model.IsValid ? 'true' : 'false';
$( document ).ready(function() {
// Any JS code here
// ...
if (isModelValid) {
setTimeout(
function () {
location.assign('/redirect_path_after_2s_delay');
},
2000);
);
}
});
<script>
I prefer typed views.
If you use untyped views, use the code below.
In your controller's action:
ViewData["IsModelValid"] = ModelState.IsValid ? "true" : "false";
return View();
In your view:
<script type="text/javascript">
var isModelValid = #ViewData["IsModelValid"];
$( document ).ready(function() {
// Any JS code here
// ...
if (isModelValid) {
// See the code above.
}
});
<script>
If the code runs in the view then you can try something like this.
is a special asp tag.
If the should indeed run in controller, than it is not possible to run JS code there.
if (ModelState.IsValid){
//lots of C# asp.net code here
<text>
<script>
jqueryFunctionName();
</script>
</text>
}
I have a question: I work with MVC an Web API and I want to use 'data-autocomplete' option for an 'input', but I don't want to get the data with '#Url.Action(string actionName, string controllerName);' , I want to get the data from the view, as a list of models pass from the controller.
Like this #model List<Project_2.Models.CartiModels>, and I don't want to autocomplete the input like this : data-autocomplete="#Url.Action("method", "controller")".
That is because I want the list loaded into the view at the first page load and be there, not generate itself every time that the client introduce another value into a textbox.
Please help me! Thank you
In Your view you can do it as follows:
<script type="text/javascript">
$(document).ready(function() {
// Assign your list to Jquery variable
var list = #Model.Name;
}
$(".txtAutocomplete").autocomplete({
// Specify the source as the jquery variable
source: function (request, response) {
$.each(list, function (index, item) { // Iterate through your list
itemList.push({ label: item.PropertyName, value: item.PropertyName2 });
});
response(itemList);
},
.....
</script>