Antd customRender return raw html - html

I need to generate html code in a customRender function of one column.
I cannot use scopedSlots as suggested here, since the html code is part of e generic component, and other components pass their columns array as a parameter.
BaseComponent.vue:
<template>
<a-table
:columns="attrs.columns"
:rowKey="record => record[attrs.recordId]"
:dataSource="filteredTableData"
>
</a-table>
</template>
<script>
export default {
props: {
attrs: {
type: Object,
required: true
}
:
</script>
ContactComponent.vue:
<template>
:
<base-component :attrs="attrs"/>
:
</template>
<script>
import BaseComponent from './BaseComponent';
export default {
components: {
BaseComponent
},
data() {
return {
attrs: {
columns: [
title: 'Type',
dataIndex: 'type',
customRender: (val, record) => {
return '<div class="myClass">' + val + </div>';
},
],
recordId: 'contactId'
}
}
}
:
</script>
The problem:
The following code:
customRender: (val, record) => {
return '<div class="myClass">' + val + '</div>';
},
renders this:
Is there a way to force raw html rendering directly from the customRender function?

You can transform your code:
customRender: (val, record) => {
return '<div class="myClass">' + val + '</div>';
},
In this way (if you have JSX support).
customRender: (data) => {
return <div class="myClass"> {data.text} </div>;
},
If you dont have JSX support, you can return a Vnode. Like specified here: https://vuejs.org/guide/extras/render-function.html#creating-vnodes (I didn't try this way).
Or you can try to add support for JSX: https://vuejs.org/guide/extras/render-function.html#jsx-tsx
(My reply is late but may help others.)
==========
Edit:
Here, another exemple, to show you where this piece of code should be (only work with JSX support):
data: function () {
return {
dataSource: [],
columns: [
{
title: 'Website',
dataIndex: "cat_website",
key: "cat_website",
customRender: (data) => {
return <a href={'http://' + data.text} target='_blank'>{data.text}</a>;
},
},
// other columns...
],
// ...
}
}

Related

Why useReducer does not update state in react-typescript

I have a problem with Typescript with React and useReducer hook. The state does not wanted to be updated and it is 100% typescript problem (I mean I need a typescript solution because in javascript it works perfect). So I want to make reducer as short as possible so I use "name" in HTML and get this name as a name of object in initialState. When I return ( title:{}, description: {}) It works but when I use [action.field] it does not work. action.field is the name of HTML element.
const initialStateReducer: inputsFormState = {
title: {
val: "",
isValid: false,
},
description: {
val: "",
isValid: false,
},
};
const RecipeForm = () => {
const inputReducer = (
state: inputsFormState,
action: inputsFormAction
): inputsFormState => {
console.log(action.type, action.content, action.field);
let isValid: boolean;
const { content } = action;
isValid = content.length > 0;
return {
[action.field]: {
val: content,
isValid: isValid,
},
...state,
};
};
const [formIsValid, setFormIsValid] = useState<boolean>(false);
const [inputsValues, dispatchReducer] = useReducer(
inputReducer,
initialStateReducer
);
const changeTextHandler = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
dispatchReducer({
type: ActionKind.changeVal,
field: e.target.name,
content: e.target.value,
});
};
return (
<React.Fragment>
<Input
name="title"
onChange={(e) => changeTextHandler(e)}
placeholder="Name for your recipe"
/>
<Textarea
name="description"
onChange={(e) => changeTextHandler(e)}
placeholder="Description"
cols={20}
rows={20}
resize="none"
/>
</React.Fragment>
);
};
Typescript is only a superset of JS that adds on Typing while writing code, it has no effect on the actually running of the JS (as it gets compiled into JS before running).
From looking at the above code I think the issue is your return in the reducer:
return {
[action.field]: {
val: content,
isValid: isValid,
},
...state,
};
Should be:
return {
...state,
[action.field]: {
val: content,
isValid: isValid,
}
};
As (and this may not be a great explanation) but right most arguments overwrite the preceding values, so you're effectively overwriting the new with the original.

next-i18next i18n on array of objects

I have an array of objects called "Options", that I use as a prop to a dropdown/select Material-UI component. I want to use the next-i18next library on the labels. I already implemented with success through all the next app just like the documentation explains. I tried using the {t('key')} and it doesn't allow.
import { useTranslation } from 'next-i18next'
const UsersPage = () => {
const { t } = useTranslation('user');
const Options = [
{ value: 'fullName', label: 'Nome' },
{ value: 'cpf', label: 'CPF' },
{ value: 'id', label: 'PadrĂ£o' },
]
...rest of the component
}
export const getStaticProps = async ({ locale }) => ({
props: {
...await serverSideTranslations(locale, ['user', 'home']),
},
})
export default UsersPage;
The msefer answer is right:
`${t("key")}`
inside JSON or string building in props like
const since = `${t('since')}`;
const until = `${t('until')}`;
...
<ListItemText
primary={value.name}
secondary={since + value.beginDate + until + value.endDate}
/>

Vue v-model on input as a dynamic ref

I created this <input> Vue component that handles a v-model property.
Adding the two-way data binding wasn't a problem, but I now want to add the current input value to the "state" so that I can clear it by just modifying a ref.
clearValue is called as expected but updating inputValue doesn't update the UI. What should I be doing differently ?
<template>
<div>
<input
:id="id"
type="text"
:value="inputValue"
#input="updateValue"
/>
<UiIcon
type="x"
#click.native="clearValue"
/>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from '#nuxtjs/composition-api';
import UiIcon from '~/components/ui/UiIcon.vue';
export default defineComponent({
name: 'UiInput',
components: { UiIcon },
props: {
id: {
type: String,
required: true,
},
value: {
type: String,
default: undefined,
},
},
setup(props, { emit }) {
const inputValue = ref(props.value);
const clearValue = () => {
inputValue.value = '';
};
const updateValue = (event: Event) => {
emit('input', (event.target as HTMLInputElement).value);
};
return {
updateValue,
clearValue,
inputValue,
};
},
});
Usage example
data() {
return { text: '' };
},
template: `
<div>
<UiInput :id="id" v-model="text" />
</div>
`,
I think you just need to emit 'input' event with empty value inside clearValue function
emit('input', '');

Vue: text field with typeahead

I want to make a text field with typeahead. I have a list of words and when you start typing them, a suggestion appears with the word(s). The thing is, it needs to be able to do it multiple times, every new word you type, it can show you a suggestion.
Anyone know how I can do this?
You can use vue-suggestion to accomplish this easily. Take a look at the demo to see if this suites you.
This is my implementation of App.vue which differs slightly.
<template>
<div>
{{ items }}
<vue-suggestion :items="results"
v-model="item"
:setLabel="setLabel"
:itemTemplate="itemTemplate"
#changed="inputChange"
#selected="itemSelected">
</vue-suggestion>
</div>
</template>
<script>
import itemTemplate from './item-template.vue';
export default {
data () {
return {
item: {},
items: [
{ id: 1, name: 'Golden Retriever'},
{ id: 2, name: 'Flying Squirrel'},
{ id: 3, name: 'Cat'},
{ id: 4, name: 'Catfish'},
{ id: 5, name: 'Squirrel'},
],
itemTemplate,
results: {}
}
},
methods: {
itemSelected (item) {
this.item = item;
},
setLabel (item) {
return item.name;
},
inputChange (text) {
// your search method
this.results = this.items.filter(item => item.name.includes(text));
// now `items` will be showed in the suggestion list
},
},
};
</script>

Trying to load json through Vue Axios

I'm trying to include a local JSON file from the static directory called blogs.json which has a load of blogs inside it.
I'm currently loading the blogs via Vue Axios which is a module I'm including in Nuxt JS.
Currently, the blogs are being loaded from the json file perfectly fine, however there is a noticeable few ms delay before the blogs are loaded, I'm trying to figure out a better approach to load the json file and populate the blogs array listed inside data()
This is my current code:
<script>
import PageBanner from '~/components/PageBanner';
export default {
head: {
title: 'Site Title: Blog',
meta: [
{ hid: 'description', name: 'description', content: 'Site description' }
]
},
components: {
PageBanner
},
data () {
return {
blogs: [],
isLoading: true
}
},
created () {
this.axios.get("/articles/blogs.json").then((response) => {
this.blogs = response.data
this.isLoading = false
})
}
}
</script>
This works just fine, but how could I modify this to load the json more quickly?
Just import it, do this and it should work God willing:
<template>
<div>
<!-- There should be no delay -->
{{blogs}}
</div>
<template>
<script>
import PageBanner from '~/components/PageBanner';
import blogsFromJson from '~/articles/blogs.json'; // Or wherever it is found
export default {
head: {
title: 'Site Title: Blog',
meta: [
{ hid: 'description', name: 'description', content: 'Site description' }
]
},
components: {
PageBanner
},
data () {
return {
blogs: blogsFromJson, // Just set it here
isLoading: true
}
},
/* No need for this anymore
created () {
this.axios.get("/articles/blogs.json").then((response) => {
this.blogs = response.data
this.isLoading = false
})
}
*/
}
</script>