I'm trying to go through a basic vue tutorial. Recently I must have changed something that is stopping anything in the vue.js from rendering on my page and I can't seem to find out why. Example: instead of displaying the value of data.product, it displays {{ Product }}. Thanks in advance for any help!Here's a link to the project repo on gitlab: project link
I'm quite sure you will see an Uncaught ReferenceError if you open the DevTools of your browser. Because in your main.js file you reference two times to non-existent variables. In your variants-array you are using Green and Blue for your variantColor as variables but non of them is defined. From context I guess you just want to display these two values as string at your page, so you have to assign a string to your variantColor variable by adding single or double quotes.
Inside your main.js change your variant array to this:
...
variants: [
{
variantId: 2234,
variantColor: 'Green'
},
{
variantId: 2235,
variantColor: 'Blue'
}
]
...
Related
I use expressjs and hbs(Handlebars) as the template engine.
One of the parameters that are passed to the template when loading the page contains HTML code.
When the page loads, instead of processing the parameter and displaying the elements, it is displayed as text.
How can I solve this?
//Server-side:
let parameter = "<h2 id="how-to-use">How To Use</h2>";
//HTML:
<div id="container">{{parameter}}</div>
//--------------------------------------
//result after page load
<h2 id="how-to-use">How To Use</h2>
//Instead of
How To Use
got it.
use the triple {{{ }}} brackets
I have a vue component whose purpose is to display a string.
The string can be very long - the one I tested had about 3 megabytes.
When trying to display string of such size the chrome tab crashes with its CPU usage going up to 100%. The console is clear.
Here's the simplified code of the component:
<template>
<div>
{{ output }}
</div>
</template>
<script>
export default {
name: "OutputField",
props: ['output']
}
</script>
The problem does not occur on Firefox.
It also disappears once the {{ output }} is commented out - which leads me to believe it has nothing to do with the logic of parent component.
Last but not least, when directly inserting the string into the innerHTML of the div, it is shown correctly even on Chrome.
I would really appreciate an explanation of this behavior and suggestions on how to display the string in a way that won't lead to it. Thanks in advance!
After looking into the problem more I managed to narrow down the possible cause to specific string messing up Vuetify's behavior in Chrome.
Created a separate question, as adding the details here would make the initial one hard to read.
It is available here: inserted into string in Vuetify crashing Chrome tab
Since the only purpose of your component is to display a value passed as a prop, you should use a functional component. It basically is a component that gets rid of the overhead that vue needs to have a state (data, methods, etc.). Instead, it will deal only with props passed to it.
You can set it up like this:
ChildComponent.vue
<template functional>
<div>{{ props.outputVal }}</div>
</template>
ParentComponent.vue
<ChildComponent outputVal="stringToDisplay">
It probably won't make the page respond instantly still, as that's a lot of data to display, but it should increase the performance by a lot and at least allow the string to display.
Here is an example of it which displays a huge string:
https://codesandbox.io/s/vue-functional-components-xbpci
I wrote a class for my project like this using typescript and react.
class myImage extends Image {
oriHeight: number;
}
After I uploaded two images I have an array named 'results' which is full of objects with type myImage.
[myImage, myImage]
When I click it in browser, I could see the data of oriHeight of each element.
Then I try to use results.map() method to traverse all the elements in that array.
results.map((result: myImage) => {
console.log(result);
var tmp = result.oriHeight;
console.log(tmp);
})
However, the output of result is no longer an object but an img tag (because the type of Image is a HTMLElement) which makes the data of result unreadable. So the output of every tmp is undefined.
I am confused about that. Why the myImage object will become an img tag when I want to traverse it? I hope someone could help me with that. Really appreciate it.
I bet your data is actually fine. When you console log an html element, the chrome console displays it as an html tag instead of the javascript object.
Update: It's generally a bad practice to add your own properties to DOM elements because they're harder to debug and you risk them being overwritten by future browser properties. Instead, you could create a javascript object that contains both the image and your custom property. Here's an example interface definition:
interface MyImage {
imageEl: HTMLImageElement;
oriHeight: number;
}
I'm using handlebars and assemble with yeoman and gulp.
I want to have some globalized partials that are able to be nested or injected into another partial by calling it within the context of a data object.
A simple example of that would be having a list of links that I could reference inside content throughout the site. The reason behind this, is the need for consistency. If for example, if I have a link within text on a page that I reference a 15 times throughout an entire website, but then realize I need to add a trade mark or modify the text, I want to update it once, not 15 times.
This is an example of what I want to do. Define global data inside a json file:
links.json
{
"apple": {
"linktext": "apple",
"target": "_blank",
"href": "http://www.apple.com"
},
"blog-article-foo-bar": {
"linktext": "foo bar",
"href": "http://www.foobar.com"
},
"dell": {
"linktext": "dell",
"target": "_parent",
"href": "http://www.dell.com"
}
}
Generate a partial from that content using a simple or complex template:
links.hbs
<a href="{{href}}" {{#if target}}target="{{target}}"{{/target}}>{{linktext}}</a>
And be able to embed that partial into another one by referencing it some how. This didn't work, but I've been reading about custom helpers, but can't figure out how I would intercept the partial and bind it into the other partial.
text.json
{
"text": "If you need a computer, go to {{> link link.apple}}."
}
text.hbs
<p>
{{text}}
</p>
compiled.html
<p>
If you need a computer, go to apple.
</p>
If you have suggestions or examples that might help me understand how to achieve this, I'd really appreciate the support. Thanks in advance.
There is some information about Handlebars helpers in their docs but not that much.
Since you're trying to use handlebars syntax in the value of a property on the context (e.g. text), handlebars won't render the value since it's already rendering the template. You can create your own helper that can render the value like this:
Handlebars.registerHelper('render', function(template, options) {
// first compile the template
const fn = Handlebars.compile(template);
// render the compiled template passing the current context (this) to
// ensure the same context is use
const str = fn(this);
// SafeString is used to allow HTML to be returned without escaping it
return new Handlebars.SafeString(str);
});
Then you would use the helper in your templates like this:
{{render text}}
Thanks for the example #doowb, your code did work but not for what I was trying to do. I really wanted something more complicated but I simplified my question not knowing it would be an issue. The code you provided worked (I think after a slight tweak) for a simple render of a template, but my templates use helpers such as #each and #if which caused the issue. Where the helpers were in my template, I ended up getting async placeholders. For example: <a $ASYNC$1$3...> I later learned this has to do with how partials are rendered. Understanding that lead me to subexpressions and the below solution.
Keeping my example above with some modifications, this is how I was able to merge partials.
First, I simplified the placeholder in text.json to basically a unique ID, instead of trying to render the partial there.
On the hbs template that I'm rendering to, such as a page or whatever, I included the insert helper with 3 arguments. The first two are subexpressions, each return a flattened partials as strings. The key here is that subexpressions process and return a result before finishing the current process with the helper. So two flattened templates are then sent to the helper along with the placeholder to search for.
The helper uses the third argument in a regex pattern. It searches the second argument (flattened parent template) for this pattern. When found, it replaces each instance of the pattern with the first argument (yes its a global fine replace).
So, the flattened child string gets inserted into parent each time placeholder is found.
First argument
(partial "link" link.apple)
Returns
'apple'
Second argument
(partial "text" text.text-example)
Returns
'<p class="text font--variant">If you need a computer, go to {{linkToApple}}.</p>'
Third argument
'linkToApple'
text.json
{
"text-example": {
"elm": "quote",
"classes": [
"text",
"font--variant"
],
"text": "If you need a computer, go to {{linkToApple}}."
}
}
text.hbs
<{{elm}} class="{{#eachIndex classes}}{{#isnt index 0}} {{/isnt}}{{item}}{{/eachIndex}}">{{text}}</{{elm}}>
compile.hbs
{{insert (partial "link" link.apple) (partial "text" text) 'linkToApple' }}
compile.html
<p class="text font--variant">If you need a computer, go to apple.</p>
gulpfile.js
app.helper('insert', function(child, parent, name) {
const merged = parent.replace(new RegExp('\{\{(?:\\s+)?(' + name + ')(?:\\s+)?\}\}', 'g'), child);
const html = new handlebars.SafeString(merged);
return html;
});
Hope this helps someone else. I know this can use improvements, I'll try to update it when I get back to cleaning up my gulp file.
I have a generic template in play 2.6, that I want to pass in a variable amount of HtmlContents. I've defined the template like this (including the implicit parameter I have in case that changes anything):
#(foo: String)(content: Html*)(implicit bar: Bar)
On the template side, this works fine-- I can dissect content with for and render it as I want. However, I haven't been able to figure out a clean way to invoke the variable arguments from the underlying template.
e.g, I have a view named "Baz":
#(something: String)(implicit bar: Bar)
In it, I try to invoke the template with multiple Html arguments. I've tried the following:
#template("fooString"){{123},{abc}}
and
#template("fooString")({123}, {abc})
and
#template("fooString"){{123}, {abc}})
And various other permutations, but inside of an enclosing bracket it seems to interpret everything literally as a single parameter in the HtmlContent vararg.
However, this ended up working as I intended, passing in multiple HtmlContents:
#template("fooString")(Html("123"), Html("abc"))
So that works, and I can use a triple-quoted interpolated string for a large Html block-- but it seems like there should be a cleaner way to do this, and the string interpolation is dangerous as it doesn't do html escaping.
Is there a way to do this using the { enclosed syntax? I'd like to understand more what is actually happening on an underlying level, and how play parses and generates HtmlContent in brackets.
So consider you have below template
// main.scala.html
#(title: String)(contents: Html*)
There are different ways you can call this template
Option #1
This is what you already posted in the question
#main("This is a title")(Html("abc"), Html("123"))
Options #2
#html1 = {
Hello
}
#html2 = {
<div>Tarun</div>
}
#main("This is a title")(html1, html2)
Option #3
#main("This is a title")(Html(<div>Tarun
</div>.toString), Html(<div>
Lalwani
</div>.toString))
Options #4
This is not exactly same option, but needs change in Template signature itself
#(title: String)(contents: List[String])
And then calling it like below
#main("This is a title")(List(
"""<div>
Tarun
</div>
""", """Hello"""))
Option #5
This requires code files and was already answered on another SO thread
Paul Draper's answer on Why doesn't this pass multiple HTML parameters to template