Delimiters in Vue 3.1+, getting started issues - vue.js

Im a little lost on this, Im trying to get started with Vue but I cannot seem to get the delimiters changed and working. Would someone be nice enough to take a look at this code and tell me if it looks like it should be working? Im using this with Django and need to change them. In addition, even experimenting with the basic tags but loading the HTML page manually in my browser doesn't seem to be working. Any ideas? I can confirm Vue is loading because I get the message in the console when it loads. I am loading this from the CDN.
const app = Vue.createApp({
el: '#table-div',
compilerOptions: {
delimiters: ["[[',']]"],
},
data(){
return {
objects: {},
text: 'This is a test',
}
}
});

OK, so in case someone else runs into issues. My particular issue is that the scripts needed to be loaded outside the ending body tag in my base.html file. I was using a template with Django and I could not get it to work within the template fragment. Loading it in the main file after the </body> tag worked like it should. I'd also add that the new compilerOptions way of changing the delimiter works as intended as well in case anyone stumbles on this trying to change the delimiter for any version 3.1+.

Related

How to render a custom component into a map's marker popup?

I am using a Vue plugin component Timeago, and i want to show a timeago time in the content of a map plugin. A super-simplified example to illustrate the usage would be something like:
let popup = L.responsivePopup().setContent(`
<h1>Hello world</h1>
<p>A thing happened <Timeago datetime="${datetime}"></Timeago></p>
`);
L.marker([lat, lon]).bindPopup(popup).addTo(this.map);
According to this answer, and Vue's documentation, i should be able to compile this using Vue.compile(), but i am not understanding the concept.
First, there is no explanation on what a "full build" is. How can i tell if what i have is a "full build"? Searching for "vuejs full build" doesn't return anything that is being referred to as literally that phrase, even though they use it in the documentation there. All i know is that when i try to call Vue.compile() with having imported import Vue from 'vue', it complains saying:
TypeError: vue__WEBPACK_IMPORTED_MODULE_6__.default.compile is not a function
So i don't know where to go from there.
And then second thing is (assuming the first thing gets sorted), will i have to make my HTML hold an empty div with a specific id, wait for it to render, and then call the Vue.compile() on it, since the sample code there runs with .mount() on an element id? Because that seems a little "incorrect", having seemingly an extra step. Or is that the only way to make this scenario work?
If there is an alternative simpler wait of making this work, like getting the Timeago component to just return the rendered string only, such as 2 hours ago that i can incorporate into my string literal, that would work for me as well. Either way is fine.
Vue has differents build of it's package, full means that package can compile templates and and run it. All build types can be found here https://v2.vuejs.org/v2/guide/installation.html#Explanation-of-Different-Builds
Vue.compile allows you to use render functions, which allow you to manipulate DOM and create elements in a programmatic way. Here you can find Vue documentation about it https://v2.vuejs.org/v2/guide/render-function.html
About the issue you are facing, you can create a vue component and put that popup inside it, this component when render will render the timeago component.
<template>
<h1>Hello world</h1>
<p>A thing happened <Timeago datetime="${datetime}"></Timeago></p>
</template>
import Timego from './Timeago.vue'
export default {
components: {
Timeago
},
props: {
datetime: String
}
}

How do I load a Vue template from a hosted html file (no webpack, etc)

I am trying a new way of writing my ui and I am using straight ESM loading with Vue. As such I am trying to load my HTML files like I would with say Webpack. I have a simple example of what I am talking about. I basically want to take...
export default {
template: "<div>Here is the component. I want this template to be an html file without webpack</div>"
// I want this to be from a url say mysite.net/viewport.html
}
I tried the simple things like
import Template from "/viewport.html"
But of course that didn't work
I think there might be something I can do with dynamic components. Has anyone tried this an come up with a good solution?

Vue component name must be lowercase?

I am trying to use a component in my view file. The following doesn't work
When I try to mount the component in my view with <CampaignCreate></CampaignCreate>
const app = new Vue({
el: '#rewards-app',
components: {
CampaignCreate,
}
});
If I change it to:
const app = new Vue({
el: '#rewards-app',
components: {
'campaign-create': CampaignCreate,
}
});
I can mount the component in my view file as <campaign-create></campaign-create> without a problem. I am trying to understand the reason behind this. I am currently on vuejs 2.x
In short, it's because HTML is case-insensitive. There was a big discussion in VueJS tracker opened 2 years ago by Evan You himself with the following reasoning:
So as we all know, HTML is case insensitive. myProp="123" gets parsed
as myprop="123" and this has led to the caveat in Vue.js where you
have to use my-prop="123" to refer to a prop declared in JavaScript as
myProp. This bites beginners quite often.
The issue was eventually closed with decision to stay on the same track. Here's a telling quote:
Essentially, the problem exists because js and html are different
technologies and use different naming systems. And using same
case(kebab or camel) in both technologies will shift weirdness from
one place to another but the underlying problem will persist So I
believe, best we can do is draw a line. and the current line i,e.
kebab case in html context and camelCase (and PascalCase) in js
context is very good.

Server Side Rendering Vue with ASP.NET Core 2

I'm trying to understand the usage and limitations of server side rendering with vuejs when using aspnet core.
I used this starter kit for aspnet core and vuejs to setup a simple vue site, which is running based on the code here: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/master
I then modified the project to update the aspnet-prerendering and added vue-server-renderer, compiling a hodgepodge of sources to cobble together this update: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/ssr
If I run this project, the site appears to load fine, and if I turn off the javascript in the browser, I can see that it does appear that the server-side rendering executed and populated the html result:
however, because JavaScript is disabled, the content isn't moved into the dom as it looks like it is trying to...
My understanding of server-side rendering is that it would populate the html entirely and serve a completed page to the user, so that even if JS was disabled, they'd at least be able to see the page (specifically for SEO purposes). Am I incorrect?
Now I believe modern search engines will execute simple scripts like this to get the content, but I still don't want a blank page rendered if js is disabled...
Is this a limitation of server-side rendering, or perhaps specifically ssr with vue and/or aspnet core?
or am I just missing a step somewhere?
Edit: more information
I looked at the source code for what I believe is the method that prerenders the section here: https://github.com/aspnet/JavaScriptServices/blob/dev/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs
The line
output.Content.SetHtmlContent(result.Html);
has a null value for result.Html. However, when I manually edit this value to put a test value, it also doesn't render to the output html, and the app div tag is still empty...
If I'm doing something wrong to populate the result.Html value with the expected output, that's one thing, and I would appreciate some help in doing that, especially since the output html appears to be found, since it's in the script that immediately follows...
However, even if I were to populate it, it appears it's being skipped, as evidenced by me manually changing the value. is this a bug in the code or am I doing somethigng wrong, or perhaps both?
As you correctly noticed, for your project, result.Html inside the tag helper is null. So that line cannot be the location where the output is being generated. Since the HTML output from your prerendering script also does not include a script tag, it is clear that something has to generate that. The only other line that could possible do this is the following from the PrerenderTagHelper:
output.PostElement.SetHtmlContent($"<script>{globalsScript}</script>");
That would fit the observed output, so we should figure out where the globalsScript comes from.
If you look at the PrerenderTagHelper implementation, you can see that it will call Prerenderer.RenderToString which returns a RenderToStringResult. This result object is deserialized from JSON after calling your Node script.
So there are two properties of interest here: Html, and Globals. The former is responsible for containing the HTML output that finally gets rendered inside the tag helper. The latter is a JSON object containing additional global variables that should be set for the client side. These are what will be rendered inside that script tag.
If you look at the rendered HTML from your project, you can see that there are two globals: window.html and window.__INITIAL_STATE__. So these two are set somewhere in your code, although html shouldn’t be a global.
The culprit is the renderOnServer.js file:
vue_renderer.renderToString(context, (err, _html) => {
if (err) { reject(err.message) }
resolve({
globals: {
html: _html,
__INITIAL_STATE__: context.state
}
})
})
As you can see, this will resolve the result containing just a globals object with both html and __INITIAL_STATE__ properties. That’s what gets rendered inside of the script tag.
But what you want to do instead is have html not as part of globals but on the layer above, so that it gets deserialized into the RenderToStringResult.Html property:
resolve({
html: _html,
globals: {
__INITIAL_STATE__: context.state
}
})
If you do it like that, your project will properly perform server-side rendering, without requiring JavaScript for the initial view.

Jquery with other libraries

I am getting an error message as element.dispatchEvent is not a function. I am using jQuery with prototype in rails 3 application. In my layout file, I have added the js files as below
javascript_include_tag 'jquery','jquery_ujs','prototype','shadowbox/shadowbox.js'
<script type="text/javascript">jQuery.noConflict();</script>
I have also added jQuery.noConflict as above and used jQuery instead of $ in jQuery functions. Any idea how to resolve this.?
In my another controller page action I have also mentioned the same thing as there are some js files which needs to be reloaded only for that particular page.
I am a newbie in js as well as rails also.
you should use jQuery.noConflict right after src to the jQuery library
Using jQuery.noConflict(); should be enough. Please check the code of the page in your browser so you can see when prototype is actually added.
You should have jQuery, then the .noConflict call, then prototype.
Besides adding the 'no conflict' method, I do this instead (though both would probably be best):
I'll 'preset' my custom script page. Let's say my prediction is that I will use maybe 5 blocks of code in a page - this is how I preset my page:
jQuery(document).ready(function($) {
// use $ in here like normal!
});
jQuery(document).ready(function($) {
});
jQuery(document).ready(function($) {
});
jQuery(document).ready(function($) {
});
etc. etc.
Notice this uses the jQuery object itself to pass as the callback function to the .ready method so you can once again use the $ identifier within the functions. I can rename it so their will never be a conflict, and I can use the $ identifier within the function like I normally would. Hope that helps.