How to share information between partial views in JS - c#

Two partials loaded on the same page
For example, if I hit a button in one partial then I want some value to appear in the other partial.
I want all the work to be done on the client side. I am sure I would call a method in js but I am not sure how to connect it to another js var on another partial within the same page. In other words how do I get both the partials to talk to eachother on the client side.

Once your razor view is rendered to the browser, It is just HTML markup. That means, you can use javascript to access the elements in the DOM and update the values as needed.
Keep your script in the main view which holds the 2 partial views.
$(function(){
$("#ButtonInFirstParial").click(function(e){
e.preventDefault();
$("#DivInSecondPartial").html("Updated");
});
});
Also if you declare your javascript variable in a global scope, you can access it in other places also. So if you have a variable like this in your layout page,
<body>
#RenderBody()
<script type="text/javascript">
var global_SiteUrl="Some value i want to access in all pages";
</script>
</body>
You can access it in other views (which uses the above one as the Layout), or js files which are a part of other views who has the layout value set as the above layout.

Related

Using Document.Ready in an MVC Partial

I am trying to use an MVC Partial to render a JavaScript grid. To do so, I have to load & utilize jQuery. However, I keep getting the following error:
$ is not defined
This should be simple...but apparently...it isn't.
THE PARTIAL LOOKS LIKE:
<h2>Inside the Partial</h2>
<div id="grid"></div>
<script type="text/javascript" defer>
// ERROR: $ is not defined
$(document).ready(function () {
// Awesome JavaScript Grid Stuff Will Go Here
});
</script>
THE VIEW LOOKS LIKE:
#using Web.Areas.Administration.ViewModels
#model LookupsViewModel
<h1>View Title</h1>
#Html.Partial(Model.PartialPath, Model.PartialModel)
Here are two main things that will help you solve your problem.
Make sure that your reference of the jQuery files is correct. Most you could had problem in the path.
Don't ever put JavaScripts in the partial views. Put those in parent view before the partial view where it has been called.
If you're loading jquery through script after the Partial view, you will be trying to run jquery variables before they are loaded and defined. Ensure that any jquery that you run (whether inline or not) is run after the page has requested and loaded jquery itself.
See: Can you write jQuery code inline before loading jQuery?
I'll give a bit more reason why you shouldn't put javascript in your partial views. If you use the Partial more than once, you risk having repeated javascript. That could mean variables are redefined, eventlisteners are added more than once, etc. causing some confusing bugs.

Conditional section in MVC

I have a twin Layout setup that renders either the entire page (with navigation) or just the contents depending on whether it was an Ajax request or not. I achieve this like so:
_LayoutRightPanel.cshtml
#{
Layout = !Request.IsAjaxRequest() ? "~/Views/Shared/_Layout.cshtml" : null;
}
This works fine for most pages, but pages that are requested via Ajax that contains #section{}s dont work (they do when loaded normally). I get the following error:
The following sections have been defined but have not been rendered
for the layout page "~/Views/Shared/_LayoutRightPanel.cshtml":
"scripts".
At the bottom of my _LayoutRightPanel I do the following to render scripts, either forcing the section to render on the main layout or rendering it on the current page if its an ajax request
#if (Request.IsAjaxRequest())
{
RenderSection("scripts", false);
}
else{
#section scripts{
#RenderSection("scripts", false)
}
}
#section scripts{
#RenderSection("scripts", false)
}
Why are you rendering the scripts section inside of the scripts section? I don't see how that can end in any way but errors or infinite recursion (which ends in an error).
Edit This is incorrect. See my update below.
RenderSection() should be used on the _Layout page (or any page that is wrapped around the current view). This is the target location (where you want the section to end up)
#section scripts{} should be used on your (Partial)View. This is the source location (where you define the section's contents).
Having both references to the same section on the same page defeats the purpose of why you should be using sections in the first place (to pass certain HTML parts to other, wrapping views (e.g. _Layout.cshtml))
Slight update
To directly answer your question, I think the error is thrown because the RenderSection call that's inside of the #section cannot find any section called "scripts" because it has not yet been defined (you're in the process of defining it).
Update
According to this SO question, duplicate names should not be an issue (so you can disregard my comment below).
However, the root cause of the issue (in that question) was that the script sections weren't chained (i.e. you can't render the section 2 layout pages up, it has to be in the specific Layout page of your view (and then keep chaining it upwards to the next Layout page).
Can you confirm that to be set up as intended?
Maybe offtopic, but is there any added value to passing the scripts section to the upper Layout page? Since you're going to render the section either way, should it not work if you always place it in the _LayoutRightPanel page?

kendo window load aspx page

Please can somebody explain how I can open up an ASPX page that is in my solution in a Kendo UI Window and get any values that I need?
What I want is to open a Kendo window with my own ASPX page which will pass an ID through to the main view after a template has been selected in the Kendo Window.
This demo shows how to load a remote page into the contents of a Window by using the content property:
window.kendoWindow({
content: "myPage.aspx"
});
Though by default it expects just HTML that it will inject into your page, so the result should not contain <html> <head> and <body> tags. However at that point the markup is just insterted into the page, so any JavaScript can directly communicate with the "parent" because they are all the same page.
You could also specify the iframe option
window.kendoWindow({
content: "myPage.aspx",
iframe: true
});
which will make the window contents an <iframe> instead of injecting it into the page.
I think your contents then could specify the <html> <head> and <body> tags just like a normal page, but now your JavaScript would have to do something different to pass a value back to the parent. That is back in the realm of normal JS, not Kendo. If I remember correctly, you can call a function in your iframe's parent by calling:
window.parent.myFunction("some value");

HTML helpers in ASP.NET MVC 3 with Javascsript action

I have many HTML helper in Helpers.cshtml file, but some of the helper (html) need some jquery action, so how do i can call jquery inside helpers.cshtml, is that possible?
i know we can keep the js file in header or particular page, but i do not want to do like that, i want to use jquery or javascript only on the page which loaded particular helper.
anyone have idea on this?
My scenario is, i have list box control, that is properly loading from helper, but i need to apply custom theme to the list box.
Little more Clarity
//in index.cshtml
#Helpers.testListBox("mylist" "1,2,3,4,5,6,7")
//in Helpers.cshtml
#helper testListBox(string listName, string listData){
//...... HTML code .........
//Javascript here?
}
With Web Forms, the framework could automatically include Javascript (once) when certain server controls were used on a page; ASP.Net MVC has no such facility. It sounds like this is what you're missing.
The way to do it is on the client. Look at RequireJS at http://requirejs.org/. This is a client-side library for managing Javascript dependencies. This does what Web Forms did, but better, and it does more. Your master layout will have a script tag like this:
<script src="/Scripts/require.js" type="text/javascript" data-main="/Scripts/main"></script>
This can be the only script tag you include on every page. Everything else can be dynamically loaded only as needed by RequireJS. It's true that you load this on every page, but it's smaller than jQuery, and it earns its place because it does so much for you.
Using your example, let's say you have this markup:
#Helpers.testListBox("mylist" "1,2,3,4,5,6,7")
and it renders HTML and needs jQuery scripting. You would render this:
// HTML for list box here
<script type="text/javascript>
require(['jquery'], function($) {
// Do your jQuery coding here:
$("myList").doSomething().whatever();
});
</script>
The require function will load jQuery, unless it has already been loaded, and then execute your code. It's true that your jQuery snippet is repeated once per use of the HTML helper, but that's not a big deal; that code should be short.
RequireJS manages dependencies effectively; you can have module A, and module B which dependes on A, and module C which depends on B. When your client code asks for module C, A and B will be loaded along with C, and in the correct order, and only once each. Furthermore, except for the initial load of require.js, scripts are loaded asynchronously, so your page rendering is not delayed by script loading.
When it's time to deploy your site on the web server, there's a tool that will examine the dependencies among the Javascript files and combine them into one or a small number of files, and then minimize them. None of your markup has to change at all. While in development, you can work with lots of small, modular Javascript files for easy debugging, and when you deploy, they are combined and minimized for efficiency.
This is much better than what the web forms framework did, and entirely client-side, which in my opinion is where it belongs.
You can put a <script> tag in the helper body.
How about this for an example of a partial view:
#model Member.CurrentMemberModel
#{
var title = "Test View";
}
<script type="text/javascript">
// Javascript goes in here, you can even add properties using "#" symbol
$(document).ready(function () {
//Do Jquery stuff here
});
</script>
#if (currentMember != null)
{
<div>Hello Member</div>
}
else
{
<div>You are not logged in</div>
}

MVC3 Layout Page, View, RenderPartial and getting script files into the Header (from the partial view)

So I have a Layout page
<head>
#RenderSection("HeaderLast", required: false)
</head>
A view
#section HeaderLast
{
<script src="#Url.Content("~/Scripts/knockout-1.2.0.js")"
type="text/javascript"></script>
}
<div id="profile-tab">
#{ Html.RenderPartial("_userProfile"); }
</div>
And a Partial view
#section HeaderLast
{
<script type="text/javascript">
alert('test');
</script>
}
<div......
I figured it couldn't be that simple. Is there a proper way to do this out of box or will this always require some kind of mediator and passing stuff around ViewData to manually make the content bubble up to the layout page?
Bounty started: The bounty will be rewarded to the best solution provided for this short coming. Should no answers be provided I will award it to #SLaks for originally answering this question.
You cannot define sections in partial views.
Instead, you can put the Javascript in ViewBag, then emit any Javascript found in ViewBag in the layout page.
#JasCav: If a partial needs its own CSS, it has no good way to get it rendered.
If that's the reason for its use, it could very well be by design.
You don't want to have a separate CSS file x partial/helper. Remember, each separate CSS file means a separate request to get it from the server, thus an additional round-trip that affects time to render your page.
Also you don't want to emit direct CSS to the HTML from the partial/helper. Instead you want it to have appropriate hooks you can use to define all the look in your site's CSS file.
You can use the same hooks you have available for CSS to activate custom JavaScript behaviors for the elements involved When JavaScript is enabled.
Finally it may be the case what you need is not a Partial View, but an extra Layout you use for some pages. With that approach you would have:
A master Layout that gets set automatically on _ViewStart like you probably has now. This defines the sections like in your sample.
A children Layout page. Here you have both the extra html, css, js you need to have for these views. This uses both #RenderBody() and #section SomeSection { } to structure your common extra layout.
Some views that point to the children layout, and others that use the default master layout.
How to get extra data to the children Layout is out of the scope of the question, but you have several options. Like having a common base for your entities; using ViewBag or calling Html.RenderAction to get that shared logic related to shared dynamic elements in the layout.
It looks like there was a similar question on SO - How to render JavaScript into MasterLayout section from partial view?.
Unfortunately, there is no possibility of declaring sections inside Partial Views. That is because RenderPartial ends up rendering totally separate view page. There is a workaround to this, though a bit ugly. But it can look better if using strongly-typed model instead of ViewData.
Basically, you need to keep track of the reference to the view which called RenderPartial and use the DefineSection method on the object passed to push data to that view.
UPDATE: There is also a blog post about dealing with RenderSection you may find useful.
Here is another approach using helper methods and templated delegate
http://blogs.msdn.com/b/marcinon/archive/2010/12/15/razor-nested-layouts-and-redefined-sections.aspx
As a follow up to my question, the JavaScript/CSS combiner/minifier tool Cassette supports this functionality to allow you to compartmentalize your JavaScript and other assets that are required for partials.
I purchased a site license and use this in all of my MVC applications now.

Categories

Resources