Returning dom element from json - javascript

I have a JSON like this:
{
"HOME_VIEW_CONTENT": {
"header": "<div>Hello <span className='someClass'>world!</span></div>",
"ingress": "Hello moon!"
}
}
then in react I have this code:
{content.header}
{content.ingress}
And this works, but i'm getting the div out as a string (naturally).
Is there a plugin or an easy way to convert the string with the div to an div object without using dangerouslyInsertInnerHtml in react?
I am using a webpack + react setup so i might use a loader? or Is there a react method for doing this?

React escapes the HTML to prevent XSS.
If you really want to render HTML, you can use dangerouslySetInnerHTML:
dangerouslySetInnerHTML={{__html: this.state.actions}}
React has this syntax so that you don't accidentally render text as HTML and introduce XSS bugs.
This is from the docs, i have not tested this as i did not need it so far.

Related

how to past object as child to script tag in react

i want to insert one html widget to my react app.
On their site it looks like this
<script>{"fieldOne":"value"}</script>
and widget works if i past this straight to html.
But when i try to do it in react app it tells me: Parsing error: Unexpected token, expected "}"
In JSX, { and } have a special meaning (wrapping JavaScript inside of the HTML/XML) so you need to have two { and two } to be able to have that:
<script>{{"fieldOne":"value"}}</script>

How do I run Prismjs in a Svelte component?

I'm simply trying to implement Prismjs into my Svelte project.
I'm loading the CSS in my <head> and I'm importing the JS in my Svelte component.
I'm running into a similar issue described here: https://medium.com/get-it-working/get-prismjs-working-in-react-a6d989e59290
Basically, it seems I need to re-run the script after the component has rendered. I'm trying to accomplish this in the same way as it's described in React in the article by running Prism.highlightAll() inside of the onMount lifecycle.
I was hoping this approach would work, but I'm not getting anywhere. I still have to refresh the page to see the styles take effect. What am I missing here?
tldr; this wasn't a Svelte issue. It was an issue with my serializer for Sanity's blocks-to-html utility.
Hi #RichHarris! Upon putting together a repo for reproduction, I found prism worked as expected. I was then able to narrow down my issue.
I should have mentioned initially, I'm using Sapper and pulling in content from Sanity. I made a modification to the serializer for Sanity's block-content-to-html utility that is converting my portable text to markup. The <pre> tag is getting data-language='HTML' from Sanity, and the Prism CSS is expecting class="language-HTML. I modified my serializer to:
code: ({node}) =>
h(
"pre",
{
"data-language": node.language, "class": "language-" + node.language
},
h("code", {}, node.code)
)
Which was working after refreshing. The class attribute was getting added, and the CSS applied. I'm just sort of thumbing through the code as I don't really know how blocksToHtml works, but upon changing the object property to className, everything is working as expected:
code: ({node}) =>
h(
"pre",
{
"data-language": node.language, className: "language-" + node.language
},
h("code", {}, node.code)
)
Thanks for taking a look, Rich! I'm really enjoying Svelte!

Display react component name in attribute

While working with React, i would like to display component name in an attribute of the component. E.g. if I have a component <LoginBox /> I would like it to be rendered as
<div data-react-name="LoginBox">...</div>
But I want this to be done automatically for each transpiled component. Reason for this is automated testing when I'd check for rendered elements in HTML/DOM, currently a component is not differentiated by the name in rendered HTML.
I thought I'd write a babel plugin, but I have no idea what visitors I'd use and how to make it robust enough. I tried google for such a plugin but I have no idea how it would be called and found nothing useful.
So is there any plugin or any way to achieve this?
Thanks
Now after a year, as I'm rethinking, it should be quite easy.
For more details on writing plugins see handbook.
Use ASTexplorer to inspect what AST would your code result in. And then, for generated tree, prepare visitors. So e.g. with code:
<div><Custom some-prop="prop">Some text</Custom></div>
we would infer, that we need to use visitor JSXOpeningElement and alter node's property attribute. To this property - array we would add a new element that we would create by Babel.types.jsxAttribute(name, value). We will get the name of tag from node's property .name.name (the name string is nested inside name object). We also need to use appropriate types. So it would look like this:
module.exports = function(Babel) {
return {
visitor: {
JSXOpeningElement(path) {
const name = Babel.types.jsxIdentifier('data-testname');
const value = Babel.types.stringLiteral(path.node.name.name);
path.node.attributes.push(Babel.types.jsxAttribute(name, value));
}
}
};
};
The code is tested with the ASTExplorer.

Using hasClass with vue.js

I know this setup I have isn't ideal however I need to check the class of an input element. I have just started using Vue.js on a new project however we have a form validation library that has to be used that uses jQuery.
The validation library I am using adds a class to an input if it doesn't fit some validation requirements.
If I was using jQuery I could just use hasClass to check if the input element had a specific class.
In Vue I am unsure how I can check if an element has a class though?
Here is an example method of what I'd like to achieve:
methods: {
nextStep: function() {
const element = this.$el.querySelector("#conversation__tram-1 input");
if (element has the class of is-valid) {
Do something
}
},
},
As you can see I'd like to check whether or not the input field has a class of is-valid. Can you think of any way I can do this with Vue.js? Thanks.
You can use the element's classList property:
if (element.classList.contains('is-valid')) {
// Do something
}
Most of the native vue.js functions involve manipulating the data behind the DOM, not the DOM itself.
There are multiple ways you can achieve this,
You can use Vue class binding, which is two-way. So you once you initialize binding then you can build an API to expose that.
Have you tried this?
if (this.$els.elementNameHere.className.match(/\bmyclass\b/)) {
//
}
If jQuery is already involved, just use its hasClass the way you already know how.
nextStep: function() {
const element = this.$el.querySelector("#conversation__tram-1 input");
if ($(element).hasClass('is-valid')) {
Do something
}
},
Vue does not provide any special DOM manipulation routines, because in Vue, you aren't generally supposed to be manipulating the DOM. There are some carved-out exceptions, but this isn't really one. :) The key to mixing jQuery and Vue is that you must be careful to separate what jQuery controls from what Vue controls so they don't step on each other's toes. Not much harm here in simply reading the DOM as long as you don't expect Vue to be updating it.

How to have all the static strings in one place

I am creating a vue webapp, I have few pages with Dynamic content and also few pages which has mostly static content. I want to move all these static strings to one place.
One option can be to use vue-i18n or vue-multilanguage, these gives support to have content files like this, but I really have no use case of support of multiple languages, so it also seems a bit over kill to me.
Another option can be to have a vuex store for all the strings, vuex I am already using for state management.
What can be good approach to do this.
I am not aware of a standard way of doing this, also this would be applicable to all the web frameworks. That said it is an interesting and valid problem.
If I had to do something about it:
I would want these strings to be available everywhere.
I would prefer not having to import these strings in all the components and each time I needed to use them.
I would want the storage space to be descriptive so that I don't have to go back and forth to check what I want to import. [The toughest part in my opinion]
To achieve 1, we can use:
Vuex
A services/some.js file which exports an object.
Plugins
I would go with plugins because:
I can get the strings by merely using this in a component, Vue.use(plugin) prevents the same plugin getting used twice, and at the same time achieve all the points (3rd will still be a tough nut to crack). Only disadvantage that I know of it might clutter the vue-instance.
So plugin can be designed like:
// stringsHelperPlugin.js
const STRING_CONST = {
[component_1_Name]: {
key1: val1,
key2: val2,
....
},
[component_2_Name]: {
key1: val1,
key2: val2,
....
},
...
}
StringConst.install = function (Vue, options) {
Vue.prototype.$getStringFor = (componentName, key) => {
return STRING_CONST['componentName'][key]
}
}
export default StringConst
in main.js this can be used like:
import StringConst from 'path/to/plugin'
Vue.use(StringConst)
and you could use this in a component template like so:
<div>
{{ $getStringFor(<component_1_name>, 'key1') }}
</div>
You can use something like this.$getStringFor(<componentName>, key) in a method. Pretty much everything that vuejs to has to offer.
Why I call the 3rd point hardest is: Maintainance if you ever change component names, you might also have to change it in the object returned by the plugin. This problem again, can be handled in many ways.
You can make an npm module with JSON files containing your strings
If you don't use vuex in your project, put your content in some javascript files which will be basically objects with all your static content and import them where you need just like Belmin menionted I am using Vue js and python flask as my backend. I want to have some local variable set. How can it be done?
A similar approach can be used for urls, configurations, errors etc.
If you use vuex, centralize everything there and make getters which you can use in each of your components.

Categories

Resources