In a ASP.NET Core MVC project I use multiple views with JQuery's DataTables objects. Previously, all these tables were initialized with a little javascript below each View (this code was at the bottom of 10-15 views):
<script>
$(document).ready(function () {
$('#table').DataTable();
});
</script>
Now, we want to change some of the settings for the whole project, so I want to get rid of all the seperate code snippets and initialize the DataTable object from one javascript. I came up with a solution, but I want to know whether this is the best way of doing it, and if not, what the best practice consists of.
I created one small javascript file, that is loaded in my _layout.chshtml file, which checks if there is a html table element (auto-generated by the razor makeup in .net core mvc):
$(document).ready(function () {
// This snippet checks whether the html of a view contains
// a #table element (id tag).
if ($('#table').length) {
$('#table').DataTable({
"pageLength": 50
// other settings
});
}
});
Is this the correct way of doing this?
Thanks for any help!
I think the way you are doing it is correct but first
you should consider whether you need this in all you pages or not?
because adding it to your layout page it will be loaded everytime any page is requested which adds at least 100kb-1MB to your page.
second you don't need the if($(..).length) JQuery will do it automatically
my suggestion for such cases is to first use a class not an ID then put your JS code here in the layout page but don't load your scripts here, load them on the pages where they are used there and before initializing check if DataTable is loaded or not.
Related
At the moment, I need to create an app that will dynamically change it's sections
This is the app layout.
The main section would be an independent webapp, because it would keep changing it's contents.
The nav bar it's basically a set of images that work as buttons and change the contents of the main section.
The side bar have some parallel uses, but it can work with the "main webapp" (the one that contains all sections
That's why I think having a nested webapp would be the best solution. I tried google site but since I can't really control it I dropped the idea.
But it's possibly to achieve that? At the moment the app need to refresh the whole page to apply even the smallest HTML change
Im a little confused, You could have that part dynamically generate information in the main section and everything else be static.
And the web app will update anytime you change the code weather its a small html changes or logic changes. unless its deployed and you dont have sync on, then you need to manually sync it to show the changes.
Update:
I solved my issue stacking divs and changing the active one by hiding the others.
I also using an include with my templates, in a way I can split my HTML code in a main template.
I use two types of includes:
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
And
function includeTemplate(template) {
return HtmlService.createTemplateFromFile(template).evaluate().getContent();
}
one used to include static HTML and other dinamic HTML (templates)
In an ASP.NET Core app, I've a dashboard with widgets. Every widget has its own PartialViews, so the full page is generated in the following way:
-Layout.cshtml
--Dashboard.cshtml
--- Widget1.cshtml
--- Widget2.cshtml
Following best practices according to fast page load times, JavaScript is loaded before the closing </body> tag in Layout.cshtml. After that, there is a section for custom JS, which I commonly use to initiate objects on page load. So this section looks like this:
<script asp-append-version="true" type="text/javascript" src="~/clientscript/page.min.js"></script>
#RenderSection("Js", required: false)
In my Views, which are using the Layout.cshtml as layout (in this example, its Dashboard.cshtml), I can define a section like
#section Js {
// Js Code here
}
which is rendered after the script tag containing all script files. So I can be sure, that all dependencies like jQuery or custom classes are avaliable here.
But I also need to do this in widgets like Widget1.cshtml for example. The problem is: I load the PartialView Widget1.cshtml in Dashboard.cshtml. In the documentation is written, that this is not possible:
If you declare a Razor section in a partial view, it will not be visible to its parent(s); it will be limited to the partial view.
But that's exactly what I need. Is there a way to work around this limitation? Shortly, the goal is to inject JavaScript from a PartialView to the LayoutView, with an regular View between them.
The only way I know is the usage of setInterval() with a low interval like 50ms, and check there if jQuery or some of my custom class is defined in a loop until they are. Its a JS solution yes. But it makes it possible to include the script-block directly in the PartialView without making usage of sections. It fits well when you depend on a single variable like jQuery.
But I need to wait for custom classes to get loaded. They're included after jQuery. So writing a generic function like waitForTypeLoaded(type, callback) is not possible. It would cause me to write always the raw setInterval() code, which seems not a smart solution for me.
Something I did to get my scripts to run after Jquery was done loading was in my Partial Views and View Components I used the "DOMContentLoaded" event to load all my jQuery js script after the page was done loading. That way I could defer the Load of jQuery and Still Have jQuery code on my pages.
<script>
window.addEventListener('DOMContentLoaded',
function() {
$('body')....
});
</script>
Your problem can be solved as mentioned in my answer to this post:
How to render scripts, generated in TagHelper process method, to the bottom of the page rather than next to the tag element?
To sum up, you can create a pair of tag helpers, one that can be located in a partial view and just stores its content in a temporary dictionary, and the other that renders the content at the appropriate position (e.g. in the layout page). I use it extensively to render small dynamically created scripts as the final scripts of the body.
Hope it helps.
Honestly, I would make one step back and look at architecture once again if you have such dilemmas.
Why not add to required scripts which will be used on a couple of views/partial views to the main layout? In ASP.NET MVC you can use bundling mechanism (or you can write our own) - minify and bundle them with other required. It won't be heavy...
Your approach looks like unnecessary complicated.
I am creating an application with Symfony2, where I have a main menu of options depending on the option selected dynamically opens a tab at a lower div with the content for that option. Content is loaded with load() of Jquery in the container div.You can see in the picture below:
The first problem was that in the HTML loaded in each tab could not use the js file initially loaded in the index.html, as you can see in this example you should check out a notice when we click the content of each tab, but does nothing .
The solution to this problem was included in each HTML code to load the appropriate script, and it worked properly. But to do it this way, if two HTML carry the same js, when one of the contents some event runs is repetite many times as tabs we have created, that is, if I open two different options (each in its own tab both charge the same js) by clicking on the first event associated performed twice, whereas if I do it in the second only done once. In short, whenever a function of a js used, is repeated as many times as there are dynamically loaded on the tabs.
And I tried event.preventDefault();orevent.stopPropagation(); and it does not solve the problem.
Would it be okay that it js is included twice in the overall structure of HTML? (Included in the initial head and then the container div)
Dynamically loading HTML + JavaScript is not the best approach for this case. I suggest that you use some JavaScript SPA framework, like AngularJS or ReactJS. Both are very big and well supported projects, so you can find tons of documentation and tutorials. You'll most likely end up using Symfony only as a RESTful service and Angular/React taking care of the rest (template loading, sending request to server, etc). Also, js frameworks will take care of deep linking and in the end you'll have a better working, easier to maintain application.
It is a bit more work initially, especially until you bootstrap the application, but then it gets easier to maintain and implement new functionality, so it pays off in the end. With your current approach you soon will find yourself in a big mess full of 100s of templates, js callbacks, inclusions, etc. I'm saying this from a personal experience!
Well...
Jquery works like this: when you attach an event to html, if the html does not exist, the event is attached to nothing. If the element exists then the event is correctly attached. It attaches only to existing elements when the on function is execute. That is a correct behaviour. In the past it used to exist a .live method that did exactly what you want: you attached an event and if you create the element after the attachment, the new element also contained the event.
Adding the js twice is not the solution. As you said after a click the button will be executed twice.
Why do not attach the events after loading the content? If you load it in the page start you can do in the main file:
$(function(){ // will force to execute the on method after all the page is loaded.
$('.submenu .button').on ('click', function (){
...
});
});
If you load the menu by ajax, in the callback and after adding the html menu to the main you must use the code I wrote above.
I am just starting out with Windows 8 development using HTML/JS. I've spent the last few months immersed in jQuery development for apps targeting vehicle head-units and televisions.
Jumping into this, I thought the transition would be simple. I have the design and structure of my site all figured out for the most part and was hoping to follow some of the practices I had been using for my previous work.
That is, I want to essentially create a single page app. The main default.html file will house the top navigation/title and one other div. The other div will be used to load in all the other pages, all separate HTML files within the project.
All of the global functions and major functionality will reside in a javascript file, application.js. Then any page-specific javascript will reside at the top of each HTML file.
I'm quickly realizing that this is a problem. Using jQuery.load() to load in my pages causes security errors in my app.
JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement.
I was really hoping to avoid having to learn a bunch of Microsoft-specific stuff. I think it's great that they've provided a lot of tools and what not, and maybe I just haven't used them enough, but everything just feels too rigid for me and for what I'm trying to do or can already be accomplished with jQuery. I'm one who likes to know EXACTLY what is happening and have full control over it.
Also looking through the templates and sample projects, I really don't like all the repeated code. For instance, every single HTML file declaring all the same references. I want to write my references and sections like my title bar just once, and not have to copy/paste that code all over my project.
Is there a way to do things the way I was hoping, and create a single page app? Do they have their own substitute for jQuery's .load()?
Any help pointing me in the right direction would be much appreciated!
EDIT 8/14/2012:
I have tried using the fix from this question:
Using jQuery with Windows 8 Metro JavaScript App causes security error
This gets rid of the security warning and I can load in HTML using jQuery.load(). However, looking at DOM explorer, my HTML is being stripped of my scripts.
I have also tried wrapping my .load() call inside of MSApp.execUnsafeLocalFunction(), but yet again my file still gets stripped of all scripts. What gives?
I fixed by simply changing the line of jQuery that was causing the error.
jQuery-1.8.0, line 5566:
append: function () {
return this.domManip(arguments, true, function (elem) {
if (this.nodeType === 1 || this.nodeType === 11) {
self.appendChild(elem); // problem line
}
});
},
Changed to:
append: function () {
return this.domManip(arguments, true, function (elem) {
if (this.nodeType === 1 || this.nodeType === 11) {
var self = this;
MSApp.execUnsafeLocalFunction(function () {
self.appendChild(elem);
});
}
});
},
There is a "formal" way to do what you are seeking.
WinJS.Navigation is provided to support "single page apps". For example, the default.html would contain a markup that would represent where the dynamically loaded page content would go:
<div id="contenthost"
data-win-control="Application.PageControlNavigator"
data-win-options="{home: '/pages/home/home.html'}">
</div>
In the example above, the actual content page loaded is at /pages/home/home.html
In event handlers, you can simply do the following to load or navigate to another page:
WinJS.Navigation.nav("/pages/other/page.html");
True, it is not jQuery, but it works great :)
Depending on your app, if you are not intending to access any WinRT components, you can navigate your page to ms-appx-web which will change the security policy around the page, but you can't specify this from start up. You would have to do a navigate, and leverage that new securyt context.
The other option you have it to wrap the calls to JQuery with msWWA.execUnsafeLocalFunction function, which will enable all that unsafe code be pushed into the DOM
In teaching students in an intro web class, I want to find the most straight-forward way of building a multipage static site of about 7 pages without having them have to make 7 different pages.
Obviously, I can have them make a separate header, footer, and menu file, and use server side includes, and just put the includes onto 7 different pages of content - but that feels dirty.
In the past I had them doing it this way: http://www.tropicalteachers.com/web110/?Ignore_WEB_119_CLEAN:MX_-old_Extra_Credit:Dynamic_PHP - this was a quick experiment using the assignment as a model: http://www.yetirobotics.org/index2.php?pagename=team_yeti
but i feel like there should be a cleaner/simpler way to do it using javascript, or maybe in php - but i'm not sure of how.
Basically i'd like one main page with a menu -and when the menu items are clicked, it loads different content. I believe it's better to have the content in seven different files, but i could imagine it all being in the same JS within one page- remember, this site should be pretty simple.
I'd like to limit it to html/css/js/php, and preferably js OR php and not both.
with just the index page controlling (and loading) everything.
Thanks!
If you want to create a more modern framework then you should look into using javascript for displaying content dynamically (as you suggested in your question). To do this I would make use of a framework like jQuery as it makes asynchronous request calling far more simple. To do this you would code a single page with a specific area marked for the dynamic content.
Server side you would setup either pages or a database to return the main content area that will change upon request.
Client side you can use jQuery's load to place the requested content into the content area.
$('#contentArea').load('url', function() {
//callback area in case there is other stuff you want to do with js
location.hash = 'blah';
});
It would probably make sense to change the page's hashmark so that pages still seem static and are linkable as content changes.
location.hash = 'blah';
In addition you will need to override default link behavior by returning false when they are clicked.
myLink.click = function() {
$('#contentArea').load('url', function() {
//callback area in case there is other stuff you want to do with js
location.hash = 'blah';
});
return false;
}
I think this would be a good lesson for students as it shows the differentiation between client-side, server-side, and how to connect them dynamically via javascript.