I want to unify the navigation layout for my website, so I created a separate html file that holds the code for the navigation. I use a JS to load the file dynamically:
$("#navigation").load("/navigation/navigation.html", function() {
$.getScript('/material.min.js');
});
The problem is that the material.min.js does not get executed for the dynamically loaded components inside this html and I lose some crucial functionality. How do I fix that?
Check if the componentHandler is loaded, and try to upgrade the elements after load.
if(!(typeof(componentHandler) == 'undefined')){
componentHandler.upgradeAllRegistered();
}
How the Component Handler works
In short this goes over all registered components. Queries for all nodes with the provided CSS class. Loops over those and instantiates them one-by-one. When the upgrade is done on a node, the upgraded object is added to the dataset. This object contains a comma separated list of component classAsString properties to identify which upgrades have been done.
From the official docs:
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function.
So loading the material.js script again will not execute it. But you can do some experiments with upgradeElements by applying it to the whole loaded markup or to particular elements.
Related
For my own project I would like to fetch HTML code from multiple Vuetify components. Not as a HTML string, but really as a DOM element that can immediately be appended to the body. I want this so that I can use these components in a non Vue environment.
Is there any way I can accomplish this?
I'm not entirely sure what your use case is for this. If you could elaborate on what you're trying to achieve, I could likely give a better answer.
I've had some similar requirement in the past, where I needed to access the entire HTML content of components/sub-components.
How I did this was by rendering the components in an iframe. From there, you can access and modify the mounted iframe DOM.
I can't find the source code on how I did this but perhaps concept/approach could serve as a starting point.
From a cursory internet search, I found this link https://jsfiddle.net/ohznser9/ with a JS Fiddle demonstrating a i-frame component that takes Vue components as a slot.
I'd imagine you could extend this component to add functionality to modify or extract elements from the DOM.
Perhaps you could load the iframe invisibly, grab the DOM elements from that and do what you wish with them
I am just currently learning React.js and I am trying to work on a simple project that can have some really heavy body content but I have to keep them in one page, so I chose tabbed components as a possible solution.
So what I'm planning is to put the tab contents into separate HTMLs and just include them into the main page hidden until their tab option is clicked, but does this mean that the HTMLs will only be loaded into the app once the tab option is clicked?
Normally I would think that the separate HTMLs would be loaded at the same time the main page is loaded, but using React.js, maybe the functionality is different?
Can someone please clarify this? Thank you very much!
A single page application is generally "loaded" immediately, and the views change based on interaction. So if you properly set up your layout, the content will be interpreted when you load the page.
What you are calling HTMLs is properly called Components. Everything in React is based on JavaScript. You would store your components in JavaScript files that end in .js not .html, and then a JavaScript function would return your JSX Component as its return value, which will trigger the DOM to reload.
In my current project I am working with a self-developed module system, where the individual modules should also have the possibility to extend e.g.the navbar by simply writing some HTML inside a <navbar:extend> tag.
It would be cool if there was a way to get it done with as little writing as the <svelte:head> tag.
What about creating a store to which you will write (update with) your HTML extensions from your Components and at the same time subscribe to that store within your NavComponent then within NavComponets append the new HTML using {#html variable}
like that you can append HTML from different components to your Navbar, this should achieve the functionality you desire.
here is a quick example of the implementation
Child1.svelte and Child2.svelte are two random components which are going to update you navbar.
Store.svelte is the file where you will create your global store to share HTML.
Nav.svelte is the navbar you want to populate with HTML from other components
try writing some HTML within Child1 and Child2 input fields then submit it, it will be rendered within the NavComponent
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.