[SOLVED] Component singleton? Render only once? Reuse DOM elements?

Hi all,

I created a component that lets the user pick a date. The component opens a “popup” (inline in the page) and instead of showing only one month, it shows the entire year. The component is “modal” so the user cannot interact with other parts of the page: Either pick a date or close the the date picker. Let’s call it <date-picker></date-picker>

I can put this on a page next to inputs of date format and everything works as intended. However I noticed that the in the DOM now I have tons of elements, because the date picker generates more than 700 elements per instance (showing day, the span container, month name, etc). If the page has 20 or more date-pickers, now we’re talking about several thousand DOM elements.

Perhaps this is not a problem, other than the page will use more memory and maybe in Internet Explorer (the slow child) the page might be slower (idk).

My question is, this is essentially the same component that gets executed (no properties, no data context) and I’m just wondering if there’s a way for it to render/generate its DOM elements only once, no matter how many times is being “instantiated”. I tried using “key” but that didn’t work.

Current work around is to tell programmers to include the component in the page (Originally, the “date input” is another component that inside puts the <date-picker>, so for now I have removed it. But I would like a solution where programmers (this will be used by about 40 programmers) don’t have to remember to also include an additional component if there are any “date fields” in the page)

Another thing that just occurred to me: Can the component in one of its life cycle events determine if another of itself already exists and abort its rendering? Or can I register with the Vue instance in a way to find out if the same component is already instantiated?

Component has no visible user interface when placed on the page (no button to click or link). The user interface is only displayed when “called”. I’m using an event mechanism and the component observes the event and opens the popup only when called. I tried using v-if, which indeed doesn’t generate the DOM elements. The downsize to this is that it takes a little longer to render when opening it (very noticeable in IE).

Hmm, what you could do is have only one instance of the component on the page, and then have each button that invokes it send an id, or the name of the variable to be edited to it.

Hi…Yes, that’s what I’m currently doing. But that requires that programmers remember to include the component on each page they intend to use it, beside the component that is the input (I wanted the “date input” to be self contained):
image

So I was just wondering if there was a way to include it in that input (attached above) and have it render only once. I tried even creating a global javascript variable to let me know if already “registered” but Vue must do some magical multi-thread rendering because to all instances the variable shows up as false.

You could render the component only at the root level, a single time.

Then have any component that needs it fire an “open” event with a callback.

1 Like

You mean to always include it in the main Vue App? hmmm…maybe I can do some injection there via mixins… I’ll see if I can do it

Any one knows how to obtain a constructor of an already registered component? All of the examples show an “object” that then can be converted into an a component.
I already have this:
Vue.component("date-picker",{all methods});

How can I get a reference to that component without polluting the global scope (like doing var mc=Vue.component("...");)

:open_mouth: Same function is used to retrieve it…great! I’ll give it a shot

Thanks! That worked like a charm!
In case any one is interested, I did a global mixin and put a mounted hook, comparing against $root to do it only in root instances.
Basically:

Vue.mixin(
{
	mounted:function()
	{
		if(this.$root===this)
		{
			var ne=document.createElement("div");
			ne.id="placeholderGLOBAL";
			this.$el.appendChild(ne);
			var dp=Vue.component("global-components");
			var idp=new dp({parent:this,el:"#placeholderGLOBAL"});
			idp.$mount();
		}
	}
});

Nice. Thats pretty similar to how vue-router is installed