Dynamic HTML via jQuery with Razor functionality - c#

Using jQuery, I am dynamically adding a group of <ul> elements to a <div> using .append. I loop through a table containing a value for each <ul> I want added. That part works fine. Where I am having an issue is trying to add Razor functionality to the <li> elements.
Although the end result HTML produced looks to be syntax correct HTML, the Razor code does not function.
End Result HTML:
<div id="div_1">
<label>Clients</label>
<ul>
#if (Model.details != null)
{
foreach (var itm in Model.details.OrderBy(i => i.value))
{
<li>#itm.value</li>}
}
</ul>
</div>
The HTML above is what is produced by my .append code. It can be hard coded into my cshtml page and works perfectly. Adding it via .append at run time does not which I assume revolves around creation time or sequence?
Scaled down version of my code below:
Controller:
[HttpGet]
public JsonResult ClientMap()
{
var db = new EDM_Client();
List<client_map> map = new List<client_map>();
map = db.client_map.ToList();
return Json(map, JsonRequestBehavior.AllowGet);
}
csHTML:
<div id="divDetails" class="row">
</div>
jQuery:
//getClientMap temporarily called from a button click
getClientMap(function (map) {
$.each(map, function (idx, obj) {
$('#divDetails').append('<div id="div_' + obj.detail_id + '">' +
'<label>' + obj.detail_hdr + '</label>' +
'<ul>' +
'#if (Model.details != null)' +
'{' +
'foreach (var itm in Model.details.OrderBy(i => i.value))' +
'{' +
'<li>' +
'#itm.value' +
'</li>' +
'}' +
'}' +
'</ul>' +
'</div>');
});
});
function getClientMap(output) {
$.ajax({
url: './Client/ClientMap',
type: "GET",
dataType: "json",
async: false,
success: function (data) {
output(data);
}
});
I am trying to do this dynamically so <ul> can be easily added/deleted via table entries rather than coding changes.
Any advice on how to make this work (or an alternative way) is appreciated.

jQuery runs on the client's machine, so when you use it to generate Razor code, the client machine cannot run that code because it has to run on the server.
You can put the Razor code directly where it should be, and then use jQuery to show/hide the options as required.
Alternatively, change your Ajax method ClientMap to return a partial view instead of JSON string, then use the jQuery's html() function to add the HTML returned from Ajax:
$('#divDetails').html(data);

Related

Converting string back to HTML

I took a HTML string from tinyMCE and wrapped it with jQuery html(). I am now trying to unwrap it and display it in the the view.
I get tinyMCE contents and put them into to a div. I then extract html contents of that div and pass it to my database via AJAX. I am now trying to convert the contents back into format that will allow me to display it properly.
<textarea name="tinycontent" class="form-control"
id="textFromContentEditor" value=""></textarea>
<div id="textContent" style="display:none"></div>
var sectionContent = tinyMCE.activeEditor.getContent();
sectionContent = $('#textContent').text(sectionContent).html();
$.ajax({
url: '/Home/CreateNoteContent',
async: false,
type: 'POST',
data: {
headerID: headerID,
categoryID: categoryID,
sectionContent: sectionContent
},
success: function (result) {
if (result == false) {
toastr.error("Cannot create new content")
} else {
toastr.success("Successfully created new content")
$("#feed-" + releaseID).trigger('click');
jumpTo(scrollPos);
}
}
});
My input into tinyMCE: Hello World
What gets stored in the db: <p>Hello World</p>
I want to be able to display just the text contents in the view.
I am certainly not very good at js, ajax and so on, but this is what I did in my project to display html in one of my divs from the pages -tag.
var blobs = document.getElementById('your-div-Id').innerHTML = "<h4>somethingRandom</h4>";
OBS! I believe this is javascript and therefor might not be the right solution.
Hope this helps!

Construct div pattern using Ajax Json

I'm going to use owl carosel.In the hardcoded div's working.Now i want to get this type via ajax function.I'll try to do this in several ways but not success.
My Webmethod it returns the Image Path & Caption values.
<div id="owl-demo">
<div class="item"><a class="item link"><img src="/Content/images/sdfdfd.png" alt="Owl Image"></a><p><center>CAPTION</center></p></div>
<div class="item"><a class="item link"><img src="/Content/images/tyty.png" alt="Owl Image"></a><p><center>CAPTION</center></p></div>
</div>
My Ajax function(instead of that hardcoded values )
function GetAllImages()
{
$.ajax({
type: "POST",
url: "/Dest/GetAllImages",
success: function (msg) {
debugger;
if (msg._allImg.length > 0) {
$.each(msg._allImg, function (index, item) {
//In here i need to construct that above pattern
//My Webmethod it returns the Image Path & Caption values.
var html = $("<div>").html();
var html2 = $("<img src").html();
$('#owl-demo').append(html);
});
}
else {
}
}
});
}
If I follow you, I think you mean:
$('#owl-demo').append('<div class="item"><a class="item link"><img src="/Content/images/' +
item.url + '" alt="Owl Image"></a><p><center>' +
item.caption + '</center></p></div>');

Mimicking a jquery hide from an MVC controller

I have a numerical "badge" value that I'm trying to display on a menu in my MVC 5.1 app.
<span id="myBadge" class="badge menu-badge">#SessionData.MyCount</span>
I have a SessionData class so I don't have to pass around magic strings.
public class SessionData
{
const string MyCountKey = "MyCount";
public static int MyCount
{
get { return HttpContext.Current.Session[MyCountKey] != null ? (int)HttpContext.Current.Session[MyCountKey] : 0; }
set { HttpContext.Current.Session[MyCountKey] = value; }
}
}
The badge is initially populated from a base controller which performs a database call.
SessionData.MyCount = CountThingsFromDatabase();
I use javascript & jquery on the front-end as users modify data. If the count reaches 0, a jquery command hides the "0" badge.
function setBadgeValue(badgeName, count) {
$(badgeName).html(count);
count > 0 ? $(badgeName).show() : $(badgeName).hide();
}
All of this works fine with one exception. When the controller retrieves a count of "0", I'd like to hide the badge from the view in the same manner as the jquery show/hide commands. The front-end jquery piece works wonderfully, but I'm unsure of how to accomplish the same effect from the controller side of things.
Any help would be greatly appreciated.
Update 1:
The views I have utilize Telerik/Kendo objects. This is from a view which displays a Kendo grid. Each grid row has a button that is tied to this method. I'm not sure it would help to post the entire view/controller since most of it is Kendo related.
function addToCart(e) {
// Get the grid data
var grid = $("#Grid").data("kendoGrid");
var dataItem = grid.dataItem(grid.select());
// Add item to the cart
$.ajax({
url: 'Search/AddCart',
data: { itemId: dataItem.ItemId },
success: function () {
$('_MyBadge').html();
$('_Layout').html();
// Update the count
setBadgeValue("#myBadge", 1);
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
alert('Failed to add item #' + dataItem.itemId + ' to your cart.\nStatus: ' + textStatus + '\nError: ' + errorThrown);
}
});
}
How about doing this on the view?
#if (SessionData.MyCount == 0)
{
<span id="myBadge" class="badge menu-badge" style="display: none;">#SessionData.MyCount</span>
}
else
{
<span id="myBadge" class="badge menu-badge">#SessionData.MyCount</span>
}
No need to use the controller in any way, just hide your badge initially in the view if your count is zero.
<span id="myBadge" class="badge menu-badge" style="display: #(SessionData.MyCount > 0 ? "block" : "none");">#SessionData.MyCount</span>

Mix Razor and Javascript code

I'm pretty confused with how to mix razor and js. This is the current function I am stuck with:
<script type="text/javascript">
var data = [];
#foreach (var r in Model.rows)
{
data.push([ #r.UnixTime * 1000, #r.Value ]);
}
If I could declare c# code with <c#></c#> and everything else was JS code -- this would be what I am after:
<script type="text/javascript">
var data = [];
<c#>#foreach (var r in Model.rows) {</c#>
data.push([ <c#>#r.UnixTime</c#> * 1000, <c#>#r.Value</c#> ]);
<c#>}</c#>
What is the best method to achieve this?
Use <text>:
<script type="text/javascript">
var data = [];
#foreach (var r in Model.rows)
{
<text>
data.push([ #r.UnixTime * 1000, #r.Value ]);
</text>
}
</script>
Inside a code block (eg, #foreach), you need to mark the markup (or, in this case, Javascript) with #: or the <text> tag.
Inside the markup contexts, you need to surround code with code blocks (#{ ... } or #if, ...)
you also can simply use
<script type="text/javascript">
var data = [];
#foreach (var r in Model.rows)
{
#:data.push([ #r.UnixTime * 1000, #r.Value ]);
}
</script>
note #:
Never ever mix more languages.
<script type="text/javascript">
var data = #Json.Encode(Model); // !!!! export data !!!!
for(var prop in data){
console.log( prop + " "+ data[prop]);
}
In case of problem you can also try
#Html.Raw(Json.Encode(Model));
A non conventional method to separate javascript from the view, but still use razor in it is to make a Scripts.cshtml file and place your mixed javascript/razor there.
Index.cshtml
<div id="Result">
</div>
<button id="btnLoad">Click me</button>
#section scripts
{
#Html.Partial("Scripts")
}
Scripts.cshtml
<script type="text/javascript">
var url = "#Url.Action("Index", "Home")";
$(document).ready(function() {
$("#btnLoad").click(function() {
$.ajax({
type: "POST",
url: url ,
data: {someParameter: "some value"},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#Result").text(msg.d);
}
});
});
});
</script>
This is my way to hack Razor and use Javascript without freaking out Intellisense.
Obviously you should use <text> but with an "expedient": double braces before.
This is what happens if a single brace is used:
This is what happen if a couple of braces are used:
Now constants and variable have been recognized.
It's better, but not good!
There is still the "less than" symbol that confuses intellisense making it think that following is the name of a tag. The "less than" sign is signaled as error and from here there are parsing errors as "console.log" shows.
You need to add something that quiets intellisense and doesn't get returned in the final JS code at compile time.
Solution: use this comment after "less than": /*>*/
This is the result
It's quite strange to see, but it works as it should.
you can use the <text> tag for both cshtml code with javascript
Wrap your Razor code in #{ } when inside JS script and be aware of using just #
Sometimes it doesn't work:
function hideSurveyReminder() {
#Session["_isSurveyPassed"] = true;
}
This will produce
function hideSurveyReminder() {
False = true;
}
in browser =(

How do I feed back current progress of code behind process to UI from jQuery AJAX call

I have a form that is going to be executing a failry long running process. Not just long, but many small steps during an install process. I'm trying to stay away from using the built in MS AJAX as much as possible in my entire application, but will use it on this page if it's just the easier way to do things.
But what I want is to only one jQuery AJAX call to code behind and have code behind spit out progess as it hits each step. Here is what I've gotten so far. It's just sample code but it's what I'm trying to do.
UI:
<head runat="server">
<title></title>
<script type="text/javascript">
$(function() {
$(this).find("#submitForm").click(function() {
RunCodeBehind();
});
});
function RunCodeBehind() {
$.ajax({
error: function(msg) { alert(msg) },
type: "POST",
url: 'Other.aspx/RunLongRunningProcess',
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(responses) {
if (responses.d != "") {
//Display process in UI
var divEvents = document.getElementById("events");
divEvents.innerText = divEvents.innerText + "\n" + data;
}
else {
//no response, update as failed
var divEvents = document.getElementById("events");
divEvents.innerText = divEvents.innerText + "No response from code behind";
}
}
});
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<a id="submitForm">Start Process</a>
<br />
<div id="events"></div>
</div>
</form>
</body>
Code behind:
[WebMethod]
public static string RunLongRunningProcess()
{
string returnValue;
var sqlQuery = "SELECT COUNT(*) FROM Users;"; //generic sql query
returnValue = ExecuteQuery(sqlQuery);
//feedback cout total to UI, continue process
var sqlQueryInsert = #"INSERT INTO Log (UserCount)
SELECT COUNT(*) FROM Users;"; //generic sql insert
returnValue = ExecuteNonQuery(sqlQueryInsert);
//feedback insert step to UI
var sqlQuery = "SELECT user + ' - ' + name + ' - ' + favday FROM Users;"; //generic sql query
returnValue = ExecuteQuery(sqlQuery);
//feedback selection to UI
return returnValue;
}
Any pointers on how to make it feed back to the UI more than once with just a single call?
I would be inclined to try the other way around, and poll another web service method from your JQuery code instead.
In your 'RunLongRunningProcess' method, I would simply update a session integer variable with values from 0 to 100.
Then I would create a separate web service method that returns the current value of this variable.
You can then poll this new method every (for example) second to get the current upload status.
I believe PeriodicalUpdater for JQuery will allow you to achieve this:
http://www.360innovate.co.uk/blog/2009/03/periodicalupdater-for-jquery/

Categories

Resources