Get ViewData in View JQuery - c#

I have a Generic List and I'm passing it as ViewData from my Controller to my .aspx View.
I need to get and iterate it with a Jquery Script.
How could I make this script works?
Regards
success: function (result) {
var myArray = new Array();
var myArray = '<%: ViewData["List"] %>';
for (var i = 0; i < myArray.length; i++) {
alert(i);
}

You can do something like this..
<script type="text/javascript">
#{ List<string> ss = (List<string>)ViewData["List"];}
var myArray = [
#for (int i = 0; i < ss.Count; i++)
{
#: #(ss[i]),
}
]
</script>
my syntax for razor view(you can do it for classic)

Try like this , push items of list view to the array of javascript, wrap below code in script tag
--script tag--
var jList = new Array();
#foreach (var item in ViewData["List"] as List<String>)
{
#:jList.push('#item'); // That will work if its a one letter string but It doesnt know that its a string untill you use ''
}
--script tag--

Ok if you are using just a list of strings then
this will do
$(document).ready(function () {
#{List<string> listFromController = (List<string>)ViewData["List"];}
var myArray = [
#for (int i = 0; i < listFromController.Count; i++)
{
#: '#(listFromController[i])',
}
]
});
But if you are passing list of another type rather than string like an student Employee or a user you will need the following
Please use the appropriate class that you have passed and the
properties suppose "UserName" could be "FirstName" "EmpId" or what ever
$(document).ready(function () {
#{ var listFromController = (List<KnockoutJSWebApi.Models.LoginViewModel>)ViewData["list"];}
var totalArray = [];
#for (int i = 0; i < listFromController.Count; i++)
{
<text>
var thisArray= {
'username': '#(listFromController[i].UserName)',
'password': '#(listFromController[i].Password)'
};
totalArray.push(thisArray);
</text>
}
});
Aspx View Engine syntax:
<script>
$(document).ready(function () {
<% List<string> listFromController = (List<string>)ViewData["List"]; %>
var myArray = [
<% for (int i = 0; i < listFromController.Count; i++){ %>
'<%: listFromController[i] %>',
<% } %>
]
debugger;
});
</script>

Problem solved.
I used a JsonResult method in my Controller and returned the needed values as:
Json(List, JsonRequestBehavior.AllowGet);
With that, I don't need to iterate the values because I assign them as datasource to my DropDownList control.
$("#Generic_FK").data("DropDownList").dataSource.data(result);
Hope to help other people with the same issue!

Server Side
public class users
{
public string name{ get; set; }
}
// in your controller code
ViewData["list"] = new List<users>(new users[] { new users()
{ name="prasad"}, new users() {name="raja"}});
Client Side
<script type="text/javascript">
$(function(){
var myitems=JSON.parse('#Html.Raw(Json.Encode(this.ViewData["list"]))');
$.each(myitems, function(index, item) {
var name = item.name;
});
});
</script>
i hope this may help you

Related

How to send List from controller/View to JS script

I have a list in Razor Page which i want to use in java script.I'm using viewdata to send data to view VIewbag is working for some reason in razor page.
I'm using .net core 2.2
Things i already tried.
View
Things i already tried:
var a=#Model.listname
var stringArray = #Html.Raw (Json.Serialize(ViewData["Quest"]));` viewdata[Quest] contains list
string jsonn = JsonConvert.SerializeObject(quelist);`
and then send jsoon to view.
using custom class object and create create json object using Newtonsoft.Json and send to view
If you proposing ajex solution explain it a little as i dont know much about it or share a link for explanation
Razor page .cs file Commented the things that didn't
public async Task OnGetAsync()
{
ViewData["opt1"] = o1list;
ViewData["quest"] = quelist;
// string jsonn = JsonConvert.SerializeObject(quelist);
// ViewData["Jon"] = jsonn;
QuestionBank = await _context.QuestionBank
.Include(q => q.QuestionLevel)
.Include(q => q.QuestionStyle)
.Include(q => q.Teacher)
.Include(q => q.Topic).ToListAsync();
Answer = await _context.Answer.ToListAsync();
QSID = await _context.QSID.ToListAsync();
View
#{var name = (List<String>)ViewData["Quest"]; }
<script>
/*function test() {
var array = #Html.Raw(Json.Serialize(ViewData["Jon"]));
for(var i = 0; i < array.length; i++) {
alert(array[i]);
console.log(array[i]);
}
}
test();
*/</script>
</head>
<body>
#{
Model.run();
var name = (List<String>)ViewData["Quest"];
var nam = (List<String>)ViewData["opt1"];
int j = 0;
for (int i = 0; i <= 4; i++)
{
var a = name[i];
<p > #a </p>
<form action="">
<input type="radio" name="s" value="">#nam[j]<br>
#{j = j + 1; }
<input type="radio" name="s" value="">#nam[j]<br>
#{j = j + 1; }
<input type="radio" name="s" value="">#nam[j]<br>
#{j = j + 1; }
<input type="radio" name="s" value="">#nam[j]
#{j = j + 1; }
</form>
}
}
I expect to get a array containing my list or in json format
This is how I do it in a project I created:
<script>
var saleTypesById = #Html.Raw(JsonConvert.SerializeObject(Model.TypesById));
</script>
Where Model.TypesById is a Dictionary<long,SaleType>.
To use from javascript I call:
var selectedSaleType = saleTypesById[selectedId];
Then I can just call properties on it like selectedSaleType.Comission
This code requires #using Newtonsoft.Json; directive and a reference to the corresponding nugget package.
I follow the above example but with an extra step:
<script type="text/javascript">
window.onload = function () {
try {
var movsArray = '#Html.Raw(JsonConvert.SerializeObject(Model))';
var opt = JSON.parse(movsArray);//Extra step
if (opt.length > 0) {
//You can use opt as array of objects
}
} catch (Error) {
console.log("Error");
}
};
</script>
or maybe you can use a loop instead of if
<script type="text/javascript">
window.onload = function () {
try {
var movsArray = '#Html.Raw(JsonConvert.SerializeObject(Model))';
var opt = JSON.parse(movsArray); //Extra step
for(var i = 0;i<opt.length;i++){
//you can use opt[i] as object, example opt[i].id
}
} catch (Error) {
console.log("Error");
}
};
</script>
Where Model is List<Mov_Tipo>

C# ASP.NET MVC Project and Google Maps: How to fill JavaScript array with values from C# List<>

I have a Class like this:
public class Markers
{
public double latitude { get; set; }
public double longitude { get; set; }
//Constructors and Methods
//(...)
}
On my Controller I have an ActionResult with a List of Markers and I add latitude and longitude like this
List<Markers> listM = new List<Markers>(); //NOTE: this is outside of my ActionResult, no problem with that.
//(...)
listM.Add(new Markers(value[0], value[1])); //NOTE: value[0] is my lat and value[1] is my longitude
//(...)
And at the end i return my list to the View:
return (listM);
Now on the View, I need to access the data and fill an array so I can display the markers on my google map.
How to fill the array with markers in position lat, long from my list?
#using ProjectName.Models
#model List<Markers>
<html>
<head>...</head>
<body>...</body>
<script type="text/javascript">
//How can I add a GoogleMap Marker ?
var markersArray = [];
#foreach(var item in Model)
{
//can't use google.maps.Marker inside this foreach =(
}
</script>
</html>
NOTE: This is how I add a marker on that array with a click on the map.
function addMarker(location) {
var marker = new google.maps.Marker({
draggable: true,
animation: google.maps.Animation.DROP,
position: location,
title: 'Bomb',
map: map,
icon: bomb
});
markersArray.push(marker);
}
Question 2:
Markers still doesn't show on map after #Leo Solution!
<script type="text/javascript">
var map;
var geocoder;
var markersArray = [];
var geoMarker;
var bomb = new google.maps.MarkerImage('Content/Images/Pins/bomb.png',
new google.maps.Size(32, 37),
new google.maps.Point(0, 0),
new google.maps.Point(22, 44)
);
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(41.287739, -7.738992),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);
#foreach(var item in Model)
{
<text>
var locations = google.maps.LatLng('#item.latitude', '#item.longitude', false);
addMarker(locations);
</text>
}
geocoder = new google.maps.Geocoder();
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(map);
}
geoMarker = new GeolocationMarker(map);
geoMarker.setCircleOptions({ fillColor: '#808080' });
google.maps.event.addListenerOnce(geoMarker, 'position_changed', function () {
map.setCenter(this.getPosition());
map.fitBounds(this.getBounds());
});
google.maps.event.addListener(geoMarker, 'geolocation_error', function (e) {
alert('There was an error obtaining your position. Message: ' + e.message);
});
geoMarker.setMap(map);
google.maps.event.addDomListener(window, 'load', initialize);
google.maps.event.addListener(map, 'click', function (event) {
addMarker(event.latLng);
});
google.maps.event.addListener(map, 'zoom_changed', function () {
var zoomLevel = map.getZoom();
//map.setCenter(myLatLng);
document.getElementById('mapzoom').innerHTML = 'Zoom: ' + zoomLevel;
});
}
function showAddress() {
alert("Vai navegar para outro endereço!");
var address = document.getElementById('txtAddress').value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: mp,
position: results[0].geometry.location
});
} else {
alert('error: ' + status);
}
});
}
function addMarker(location) {
var marker = new google.maps.Marker({
draggable: true,
animation: google.maps.Animation.DROP,
position: location,
title: 'Bomba',
map: map,
icon: bomb
});
markersArray.push(marker);
}
function setAllMap(map) {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(map);
}
}
function clearMarkers() {
setAllMap(null);
}
function showMarkers() {
setAllMap(map);
}
function deleteMarkers() {
clearMarkers();
markersArray = [];
}
function loadScript() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&' +
'callback=initialize';
document.body.appendChild(script);
}
window.onload = loadScript;
if (!navigator.geolocation) {
alert('Your browser does not support geolocation');
}
</script>
Try this.....
<script>
var markersArray = [];
var _map = null;
var _c = null;
#foreach(var item in Model)
{
<text>
markersArray.push(new google.maps.Marker({
draggable: true,
animation: google.maps.Animation.DROP,
position: new google.maps.LatLng('#item.latitude', '#item.longitude', false),
title: 'Whatever title',
map: _map
}));
</text>
}
</script>
Second Question
I had to carefully look at your code and found 3 problems...one of them you've already mentioned it. The other ones are that you are duplicating variable names and you are not instantiating a new object. Now change this....
#foreach(var item in Model)
{
<text>
var locations = google.maps.LatLng('#item.latitude', '#item.longitude', false);
addMarker(locations);
</text>
}
to this....
#foreach(var item in Model)
{
<text>
addMarker(new google.maps.LatLng(parseFloat('#item.latitude'), parseFloat('#item.longitude')));
</text>
}
Let me know how it goes

Organizing ordered results into labeled sections

I am trying to properly place my returned results into labeled sections - example of what i mean.
Controller:
public IEnumerable<Users> GetUserList(int? id, int? pageNumber)
{
if (!id.HasValue)
throw new HttpResponseException(HttpStatusCode.NotFound);
int _pageNum = pageNumber.HasValue ? pageNumber.Value : 1;
return new UserService().GetUsers(id.Value, pageNumber: _pageNum);
}
View:
<div id="listView" data-bind="template: { name: 'list', foreach: Users }">
<section id="Images">
<section id="users"></section>
</section>
</div>
knockout.js/jquery: UPDATED
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// The ViewModel for the page
var viewModel = {
Users: ko.observableArray([]),
users: ko.observableArray([]),
groups: ko.computed({
read: function(){
var groups = [];
var groupLetter;
for(var i = 0; i <letters.length; i++){
viewModel.Users.groups[letters[i]].users([]);
}
ko.utils.arrayForEach(viewModel.users(), function (user) {
groupLetter = user.name()[0].toUpperCase();
if (groups.indexOf(groupLetter) < 0) {
groups.push(groupLetter);
}
groups[groupLetter].users.push(user);
});
return groups.sort();
},
deferEvaluation: true
}),
};
for (var i = 0; i < letters.length; i++) {
viewModel.users.groups[letters[i]] = { users: ko.observableArray([]) };
}
// The ViewModel for the page
var viewModel = {
Users: ko.observableArray([]), //already a sorted list of users
TotalRoster: null,
CurrentPage: ko.observable(1),
DataIsLoading: ko.observable(false),
};
So this returns in the view:
Amanda
Bob
Frank
Kate
Tim
I would like to have this displayed in the view:
A (Header)
Amanda
B (Header)
Bob
F (Header)
Frank
K (Header)
Kate
T (Header)
Tim
Mainly for a visual reference for viewers to see - it will show letter headers for the users that exist so if there are no users with a name that starts with S then there won't be a S header. Any help as to where i could look into or what this could be called i could read about that would be great.
You can group the users by their name on client side as follow :
// assuming the array is sorted
var users = ['Amanda', 'Anna', 'Bob', 'Frank', 'Francois', 'Sam'];
var lastGroup = null;
var vm = {
groups: []
};
ko.utils.arrayForEach(users, function (user) {
// known group
if (lastGroup && lastGroup.name == user[0]) {
lastGroup.users.push(user);
} else {
// unknown group
lastGroup = {
name :user[0], users : [user]
};
vm.groups.push(lastGroup);
}
});
<div data-bind="foreach:groups">
<span data-bind="text:name" style="font-weight: bold"></span>
<br/>
<div data-bind="foreach:users">
<span data-bind="text:$data"></span>
<br/>
</div>
</div>
See fiddle
I can tell you that you're not going to be able to do this by just looping through the Users array in the binding. Each iteration through will generate that templated html code provided for each of the User objects.
One approach I would consider is creating a dynamic array of groups that are based on the first letter of the User's name and attach these to the root observableArray object.
function ViewModel() {
var self = this;
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
self.users = ko.observableArray([]);
self.users.groups = ko.computed({
read: function(){
var groups = [];
var groupLetter;
for (var i = 0; i < letters.length; i++) {
self.users.groups[letters[i]].users([]);
}
ko.utils.arrayForEach(self.users(), function (user) {
groupLetter = user.name()[0].toUpperCase();
if (groups.indexOf(groupLetter) < 0) {
groups.push(groupLetter);// not listed? Add it
}
self.users.groups[groupLetter].users.push(user);// Add to the grouped users array
});
return groups.sort();
},
deferEvaluation: true
});
for (var i = 0; i < letters.length; i++) {
self.users.groups[letters[i]] = { users: ko.observableArray([]) };
}
}
Now in your View:
<div data-bind="foreach: { data: $root.users.groups, as: '$group' }">
<h3 data-bind="text: $group"></h3>
<ul data-bind="foreach: { data: $root.users.groups[$group].users, as: '$user' }">
<li data-bind="text: $user.name"></li>
</ul>
</div>
jsFiddle
*Note: You'd only want to go this route if you had a need to update these names dynamically on the client side. If this list were to remain static, it'd probably be best to go with Damien's answer.

dynamically creating select elements and populating options from sharepoint list

The code I wrote works, but it could be better. I am writing out the same function three times, one for each of the combo box elements. I am stuck on how to make this more efficient. I have looked at creating an object and putting each of the variables in an array, but I was not able to successfully get it working.
var csCategory = <%=csCategoryArray%>,
csKeyword = <%=csKeywordArray%>,
csEntity = <%=csEntityArray%>;
addOption = function (selectbox, text, value) {
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
}
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox1")
if (selectObj) {
for (var i=0; i < csCategory.length;++i){
addOption(selectObj, csCategory[i], csCategory[i]);
}
}
});
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox2")
if (selectObj) {
for (var i=0; i < csKeyword.length;++i){
addOption(selectObj, csKeyword[i], csKeyword[i]);
}
}
});
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox3")
if (selectObj) {
for (var i=0; i < csEntity.length;++i){
addOption(selectObj, csEntity[i], csEntity[i]);
}
}
});
The obvious first step is to refactor out the shared code. So:
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox2")
if (selectObj) {
for (var i=0; i < csKeyword.length;++i){
addOption(selectObj, csKeyword[i], csKeyword[i]);
}
}
});
( ... etc ... )
becomes:
function populate(id, collection) {
var selectObj = document.getElementById(id)
if (selectObj) {
for (var i=0; i < collection.length;++i){
addOption(selectObj, collection[i], collection[i]);
}
}
}
$(function () {
populate ("combobox1", csCategory);
populate ("combobox2", csKeyword);
populate ("combobox3", csEntity);
});
I can't see any significant advantage at this stage of putting combobox1 and its siblings into an array, but it may be worthwhile revisiting this code if more comboboxes are added in the future.

paging a heavy document using jquery and mvc

I have a html document but it's size is about 5MB.
Here is my code "../Product/index?page=1" it generates 5MB html :
Plugin url : http://andersonferminiano.com/jqueryscrollpagination/
<script type="text/javascript">
$(function () {
$('#content').scrollPagination({
'contentPage': '../Product/index?page=1',
'contentData': {},
'scrollTarget': $(window),
'heightOffset': 10,
'beforeLoad': function () {
$('#loading').fadeIn();
},
'afterLoad': function (elementsLoaded) {
$('#loading').fadeOut();
var i = 0;
$(elementsLoaded).fadeInWithDelay();
if ($('#content').children().size() > 100) {
$('#nomoreresults').fadeIn();
$('#content').stopScrollPagination();
}
}
});
$.fn.fadeInWithDelay = function () {
var delay = 0;
return this.each(function () {
$(this).delay(delay).animate({ opacity: 1 }, 200);
delay += 100;
});
};
});
</script>
<!--_____________________________________________________________________-->
#{
// here is "Product/index" Code
if (Request.QueryString.HasKeys())
{
int iPage = Request.QueryString["page"].AsInt();
using (var db = new PNUBOOKIR.Models.KowsarSiteEntities())
{
var queries = from n in db.vwGood
select n;
long counter = 0;
for (int i = 1; i <= iPage; i++)
{
foreach (var q in queries)
{
counter++;
<li style="opacity: 0; -moz-opacity: 0; filter: alpha(opacity=0);">
<p>
#counter
</p>
</li>
}
}
}
}
}
I don't want to load it complete when the scroll goes down it should load 10 other "li" element
I do not simulate so heavy page, but I have an other way to load page. Maybe, it can be a reference for you.
Separate each page request at action side, and return for only one page content.
Collect "style" content to css class, to reduce page content.
Improve performance of LINQ with PLINQ.
I notice the code output every page content.
var queries = from n in db.vwGood select n;
long counter = 0;
for (int i = 1; i <= iPage; i++)
{
foreach (var q in queries)
{
counter++;
}
}
I suggest you can
modify LINQ with Paging function.
Update LINQ as PLINQ to improve performance. I add AsParallel() after db.vwGood, I am not sure what db.vwGood instance and wish this modify can be good.
Not return HTML content in Razor View, but in Action.
Pseudo code of Action is as below,
// iAmount is record amount in each page.
int iAmount = 50;
// queries is only the iPage content
// but not all of content from page one to page iPage.
var queries = (from n in db.vwGood.AsParallel() select n)
.Skip(iPage - 1).Take(iAmount);
long counter = 0;
string strContent = string.Empty;
foreach (var q in queries)
{
counter++;
// Generate Cotnent here.
strContent += #"<li class='YourClassName'><p>#counter</p></li>"
}
return Content(strContent)
When ShowMore button is clicked, ShowMore_OnClick() is performanced.
<input type="button" style="width: 100%" id="BtnShowMore" value="MORE"
onclick="return ShowMore_OnClick();" />
This is JavaScript for Loading function.
I notice you do not use button to control content display, but scrollPagination. You can modify the JavaScript to suit with scrollPagination plugin. The thinking of code structure is same.
var PageNO = 1;
function ShowMore_OnClick() {
var BtnShowMore = document.getElementById("BtnShowMore");
BtnShowMore.value = "Loading...";
jQuery.post(
"/Home/GetHomeEventAjax/",
{ "PageNO": PageNO + 1 },
function (data, states) {
if (states == "success") {
var EventListArea = document.getElementById("EventListArea");
var newCommentItem = document.createElement("DIV");
newCommentItem.setAttribute("ID", "EventItem");
newCommentItem.innerHTML = data;
EventListArea.appendChild(newCommentItem);
PageNO = PageNO + 1;
BtnShowMore.value = "More";
}
}
);
}

Categories