So I am using this input template I got from a tutorial #logaretm created, which works great for just about anything I need. I would like to know if there is a way to modify this template to validate as a Select (drop-down) and how would I populate the option values?
I looked at vee-validation documentation but haven't been able to figure this out on my own. Any help would with this is greatly appreciated.
<template>
<div
class="TextInput"
:class="{ 'has-error': !!errorMessage, success: meta.valid }"
>
<label :for="name">{{ label }}</label>
<input
:name="name"
:id="name"
:type="type"
:value="inputValue"
:placeholder="placeholder"
#input="handleChange"
#blur="handleBlur"
/>
<p class="help-message" v-show="errorMessage || meta.valid">
{{ errorMessage || successMessage }}
</p>
</div>
</template>
<script>
import { toRef } from "vue";
import { useField } from "vee-validate";
export default {
props: {
type: {
type: String,
default: "text",
},
value: {
type: String,
default: "",
},
name: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
successMessage: {
type: String,
default: "",
},
placeholder: {
type: String,
default: "",
},
},
setup(props) {
// use `toRef` to create reactive references to `name` prop which is passed to `useField`
// this is important because vee-validte needs to know if the field name changes
// https://vee-validate.logaretm.com/v4/guide/composition-api/caveats
const name = toRef(props, "name");
// we don't provide any rules here because we are using form-level validation
// https://vee-validate.logaretm.com/v4/guide/validation#form-level-validation
const {
value: inputValue,
errorMessage,
handleBlur,
handleChange,
meta,
} = useField(name, undefined, {
initialValue: props.value,
});
return {
handleChange,
handleBlur,
errorMessage,
inputValue,
meta,
};
},
};
</script>
Related
I have added a custom tab on my module’s details page, however, the tab is rendered but the content for the tab isn’t showing. There isn’t any error in the console log as well.
index.js
import './page/wt-shopfinder-list';
import './page/wt-shopfinder-detail';
import './view/wt-shopfinder-detail-base';
import './view/wt-shopfinder-detail-review';
const { Module } = Shopware;
Module.register('example-shopfinder', {
type: 'plugin',
name: 'ExampleShopFinder',
title: 'example-shopfinder.general.mainMenuItemGeneral',
description: 'example-shopfinder.general.descriptionTextModule',
version: '1.0.0',
targetVersion: '1.0.0',
color: '#9AA8B5',
icon: 'default-shopping-paper-bag',
entity:'wt_shop_finder',
routes: {
index: {
components: {
default: "wt-shopfinder-list"
},
path: 'index',
},
detail: {
component: 'wt-shopfinder-detail',
path: 'detail/:id',
redirect: {
name: 'example.shopfinder.detail.base',
},
children: {
base: {
component: 'wt-shopfinder-detail-base',
path: 'base',
meta: {
parentPath: 'example.shopfinder.index'
},
},
review: {
component: 'wt-shopfinder-detail-review',
path: 'review',
meta: {
parentPath: 'example.shopfinder.index'
},
},
},
meta: {
appSystem: {
view: 'detail',
},
},
props: {
default(route) {
return {
shopFinderId: route.params.id,
};
},
},
}
},
navigation: [{
id: 'wt-shopfinder',
label: 'example-shopfinder.menu.mainMenuItemGeneral',
color: '#ff3d58',
icon: 'default-shopping-paper-bag-product',
path: 'example.shopfinder.index',
parent: "sw-marketing",
position: 100,
}],
});
wt-shopfinder-detail/wt-shopfinder-detail-html.twig
<sw-tabs
class="wt_shopfinder-detail-page__tabs"
position-identifier="wt-shopfinder-detail"
>
{% block wt_shopfinder_detail_content_tabs_general %}
<sw-tabs-item
:route="generalRoute"
:title="$tc('sw-customer.detail.tabGeneral')"
:disabled="false"
>
{{ $tc('sw-promotion-v2.detail.tabs.tabGeneral') }}
</sw-tabs-item>
{% endblock %}
{% block wt_shopfinder_detail_content_tabs_general2 %}
<sw-tabs-item
:route="reviewRoute"
:title="$tc('sw-customer.detail.tabGeneral')"
:disabled="false"
>
Review
</sw-tabs-item>
{% endblock %}
</sw-tabs>
wt-shopfinder-detail/index.js
//Sharing only the url part for tab navigation
generalRoute() {
console.log("ID = "+this.shopFinderId);
return {
name: 'webbytroops.shopfinder.detail.base',
params: { id: this.shopFinderId },
};
},
wt-shopfinder-detail-base/index.js
import template from './wt-shopfinder-detail-base.html.twig';
const { Component } = Shopware;
const { Criteria } = Shopware.Data;
Component.register('wt-shopfinder-detail-base', {
template,
inject: ['repositoryFactory'],
metaInfo() {
return {
title: "Custom"
};
}
});
wt-shopfinder-detail-base/wt-shopfinder-detail-base.html.twig
<sw-card title="Custom">
Hello world!
</sw-card>
The correct pattern for the route would be {moduleName}.{routeName}.{childName} and in the module name dashes are replaced by dots. So the correct route in your case should be example.shopfinder.detail.base.
Also, unless you omitted it, you're missing the router-view tag after the sw-tabs component.
<sw-container>
<sw-tabs>
...
</sw-tabs>
<router-view />
</sw-container>
I am learning MERN and would like to display the list of messages from Mongo Database in React UI.
My UserSchema in Mongo:
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
phone: {
type: Number,
required: true,
},
messages: [
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
phone: {
type: Number,
required: true,
},
message: {
type: String,
required: true,
},
},
],
tokens: [
{
token: {
type: String,
required: true,
},
},
],
});
Code in Home.js in React:
import React, { useState, useEffect } from "react";
const Home = () => {
const [userName, setUserName] = useState({});
const [show, setShow] = useState(false);
const userHome = async () => {
try {
const res = await fetch("/userdata", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const data = await res.json(); //successfully getting complete json data in console.
console.log(data);
setUserName(data);
setShow(true);
} catch (err) {
console.log(err);
}
};
useEffect(() => {
userHome();
}, []);
return (
<>
<div className="page-wrap d-flex flex-row align-items-center">
<div className="container">
<div className="row justify-content-center">
<div className="col-md-12 text-center">
<span className="display-1 d-block">
<p> Welcome {show ? "Back!" : ""} </p>
<h1>{userName.name}</h1>
<h2>
{show
? "What you want to do today?"
: "Your own Portal.."}
</h2>
</span>
<div className="mb-4 lead">
{show
? ""
: "You need to register and login for accessing your profile."}
</div>
<div>
<div>Messages:{userName[0].message}</div>
{/* wants to display list of all message here */}
</div>
</div>
</div>
</div>
</div>
</>
);
};
export default Home;
My approach to try fetching the list of all messages
I tried map method but not succeeded and tried below code still no success. Kindly advise. I want to display all the messages Message 1, Messag 2 etc. upon loading.
<div>Messages:{userName[0].message}</div>
Error Message in Browser:
TypeError: Cannot read properties of undefined (reading 'message')
I got it solved as below
Removed
<div>Messages:{userName[0].message}</div>
{/* wants to display list of all message here */}
</div>
Added:
<div>
{userName.messages?.map((msg1) => (
<li key={msg1._id}>{msg1.message}</li> ))}
</div>
can you delete this part:
<div>
<div>Messages:{userName[0].message}</div>
{/* wants to display list of all message here */}
</div>
and add this instead:
<div>{
data.map(result => (
<div key={result._id}>
<h2>{result.name}</h2>
<p>Some text: {result.messages}</p>
</div>
))
}</div>
If above code works, then you can tweak it to display your desired message which i think is this:
<p>Some text: {result.messages[0].message}</p>
Please let me know if it works.
Good afternoon, I am new to react and node.js and I have a problem.
I have a table on a web page where you will receive the data for a trip. The columns (Id locales, name, date, time) are present in the travel_order model, but the column "localities name" is intended to list the name of the localities using the id. The ids for this location are listed in the "Localities Id" column. However, when listing, it gives me the error: "TypeError: Cannot read property 'designacao' of undefined".
For a better understanding of the table, in the first line of data, 1 is the departure id and 124 is the arrival id. I've uploaded a photo of the table as well as the controller and models.
the insertion of the data in the table is done in the function loadFillData () present in this code:
import React from 'react';
import '../../../assets/css/Pagamentos.css'
import 'js-datepicker/dist/datepicker.min.css';
import '../../../assets/css/bootstrap.css';
import axios from 'axios';
import { data } from 'jquery';
const datepicker = require('js-datepicker');
class Pagina extends React.Component {
constructor(props) {
super(props);
this.state = {
pag_pendentes: []
}
}
componentDidMount() {
const picker = datepicker('#calendario', {
formatter: (input, date, instance) => {
input.value = new Intl.DateTimeFormat('en-GB').format(date)
}
});
const url = "http://localhost:3001/operadora/pendente";
axios.get(url)
.then(res=>{
if(res.data.success){
const data = res.data.data;
this.setState({pag_pendentes:data});
}else{
alert("Erro");
}
})
.catch(error=>{
alert(error)
});
}
render() {
return (
<div>
<div id="div-filtragem">
<label className="Label_DatePicker">Data inicio:</label>
<input placeholder="Selecione uma data" type="text" id="calendario" className="form-control DatePicker datepicker" style={{ width: "auto" }} />
<label className="Label_DatePicker">Data fim:</label>
<input placeholder="Selecione uma data" type="text" id="calendario" className="form-control DatePicker datepicker" style={{ width: "auto" }} />
<button type="button" className="ButtonFilter ">Filtrar</button>
</div>
<div className="div_tabela">
<table className="table tabela" >
<thead>
<tr>
<th scope="col">IDs localidades</th>
<th scope ="col">nome localidades</th>
<th scope="col">Nome</th>
<th scope="col">Data</th>
<th scope="col">Hora</th>
<th scope="col">Valor</th>
</tr>
</thead>
<tbody>
{this.loadFillData()}
</tbody>
</table>
</div>
</div>
);
}
loadFillData(){
console.log(this.state.pag_pendentes);
return this.state.pag_pendentes.map((data, index) => {
return (
<tr key ={index}>
<td className="td_viagem">{data.partida + "-"+data.chegada}</td>
<td>{data.pp.designacao + "-"+data.pc.designacao}</td>
<td>{data.pessoa.p_nome + " " +data.pessoa.u_nome}</td>
<td>{data.data_viagem}</td>
<td>{data.hora_viagem}</td>
<td>10€</td>
</tr>
)
});
}
}
export default Pagina;
The controller:
var Viagem = require('../../model/viagem');
var Pedido_viagem = require('../../model/pedido_viagem');
var Estado = require('../../model/estado');
var Pessoa = require('../../model/pessoa');
var Partida = require('../../model/freguesias');
var Chegada = require('../../model/freguesias');
const sequelize = require('../../model/database');
const op_pagamentos = {}
sequelize.sync()
op_pagamentos.pendentes = async(req,res) => {
const data = await Pedido_viagem.findAll({
include: [Viagem],
include: [Estado],
include:[{
model: Partida,
as:'pp',
attributes:['designacao']
},
{model: Chegada,
as:'pc',
attributes:['designacao']}],
include: [{
model: Pessoa,
attributes:['p_nome', 'u_nome']}],
where:{
estado : "3",
},
order :[[ 'id', 'asc' ]],
})
.then(function (data) {
return data;
})
.catch(error => {
console.log('Erro: ' + error);
return error;
});
res.json({success: true, data: data});
}
module.exports = op_pagamentos;
model pedido_viagem:
var Sequelize = require('sequelize');
var sequelize = require('./database');
var Municipe = require('./pessoa');
var Estado = require('./estado_pedido');
var Partida = require('./freguesias');
var Chegada = require('./freguesias');
var pedido_viagem = sequelize.define('pedido_viagem',{
id:{
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
municipe:{
type: Sequelize.INTEGER,
references:{
model:Municipe,
key:'id'
},
allowNull:false // coloca variável NOT NULL
},
partida:{
type: Sequelize.INTEGER,
references:{
model:Partida,
key:'id'
},
allowNull:false // coloca variável NOT NULL
},
chegada:{
type: Sequelize.INTEGER,
references:{
model:Chegada,
key:'id'
},
allowNull:false // coloca variável NOT NULL
},
data_viagem: {
type:Sequelize.DATE,
allowNull:false // coloca variável NOT NULL
},
hora_viagem:{
type:Sequelize.TIME,
allowNull:false // coloca variável NOT NULL
},
aceita_partilha:{
type:Sequelize.INTEGER,
allowNull:false // coloca variável NOT NULL
},
necessidades_especiais: {
type:Sequelize.INTEGER,
allowNull:false // coloca variável NOT NULL
},
bagagem: {
type:Sequelize.INTEGER,
allowNull:false // coloca variável NOT NULL
},
estado:{
type:Sequelize.INTEGER,
references:{
model: Estado,
key:'id'
}
}
},
{
timestamps: false,
freezeTableName: true
});
pedido_viagem.belongsTo(Municipe,{foreignKey:'municipe'});
pedido_viagem.belongsTo(Partida,{as:'pp',foreignKey:'partida'});
pedido_viagem.belongsTo(Chegada,{as:'pc',foreignKey:'chegada'});
module.exports= pedido_viagem;
model freguesias:
var Sequelize = require('sequelize');
var sequelize = require('./database');
var tipo_freguesia = require('./tipo_frequesia');;
var freguesia = sequelize.define('freguesias',{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
designacao: {
type:Sequelize.CHAR(50),
allowNull:false // coloca variável NOT NULL
},
localizacao: {
type: Sequelize.CHAR(100),
allowNull:false // coloca variável NOT NULL
},
zona: {
type:Sequelize.INTEGER,
allowNull:false // coloca variável NOT NULL
},
tipo_freguesia:{
type: Sequelize.INTEGER,
regerences:{
model:tipo_freguesia,
key:'id'
},
allowNull:false // coloca variável NOT NULL
}
},
{
timestamps: false,
freezeTableName: true,
});
module.exports = freguesia;
Log file:
Node.js Log:
Please, thank you very much if anyone can help me. I am a beginner and I do not understand why I am getting this error.
Greetings to all.
The problem lies here:
include: [Viagem],
include: [Estado],
include:[{
model: Partida,
as:'pp',
attributes:['designacao']
},
{model: Chegada,
as:'pc',
attributes:['designacao']}],
include: [{
model: Pessoa,
attributes:['p_nome', 'u_nome']}]
You are overwriting include which will resolve to use only last one, instead you should use the include as an array:
include: [Viagem, Estado, {
model: Partida,
as:'pp',
attributes:['designacao']
},
{model: Chegada,
as:'pc',
attributes:['designacao']}, {
model: Pessoa,
attributes:['p_nome', 'u_nome']}]
I am following a tutorial for a React+Redux fullstack and the instructor did something strange that is not working for me.
Specifically these lines, in the submitForm() class:
this.props.dispatch(registerUser(dataToSubmit))
.then(response =>{
Are causing error:
TypeError: this.props.dispatch(...).then is not a function
This is the whole class:
import React, { Component } from 'react';
import FormField from '../utils/Form/formfield';
import { update, generateData, isFormValid } from '../utils/Form/formActions';
import { connect } from 'react-redux';
import { registerUser } from '../../actions/user_actions';
class Register extends Component {
state = {
formError: false,
formSuccess:false,
formdata:{
name: {
element: 'input',
value: '',
config:{
name: 'name_input',
type: 'text',
placeholder: 'Enter your username'
},
validation:{
required: true
},
valid: false,
touched: false,
validationMessage:''
},
email: {
element: 'input',
value: '',
config:{
name: 'email_input',
type: 'email',
placeholder: 'Enter your email'
},
validation:{
required: true,
email: true
},
valid: false,
touched: false,
validationMessage:''
},
password: {
element: 'input',
value: '',
config:{
name: 'password_input',
type: 'password',
placeholder: 'Enter your password'
},
validation:{
required: true
},
valid: false,
touched: false,
validationMessage:''
},
confirmPassword: {
element: 'input',
value: '',
config:{
name: 'confirm_password_input',
type: 'password',
placeholder: 'Confirm your password'
},
validation:{
required: true,
confirm: 'password'
},
valid: false,
touched: false,
validationMessage:''
}
}
}
updateForm = (element) => {
const newFormdata = update(element,this.state.formdata,'register');
this.setState({
formError: false,
formdata: newFormdata
})
}
submitForm= (event) =>{
event.preventDefault();
let dataToSubmit = generateData(this.state.formdata,'register');
let formIsValid = isFormValid(this.state.formdata,'register')
if(formIsValid){
this.props.dispatch(registerUser(dataToSubmit))
.then(response =>{
if(response.payload.success){
this.setState({
formError: false,
formSuccess: true
});
setTimeout(()=>{
this.props.history.push('/register_login');
},3000)
} else {
this.setState({formError: true})
}
}).catch(e => {
this.setState({formError: true})
})
} else {
this.setState({
formError: true
})
}
}
render() {
return (
<div className="page_wrapper">
<div className="container">
<div className="register_login_container">
<div className="left">
<form onSubmit={(event)=> this.submitForm(event)}>
<h2>Personal information</h2>
<div className="form_block_two">
<div className="block">
<FormField
id={'name'}
formdata={this.state.formdata.name}
change={(element)=> this.updateForm(element)}
/>
</div>
</div>
<div>
<FormField
id={'email'}
formdata={this.state.formdata.email}
change={(element)=> this.updateForm(element)}
/>
</div>
<h2>Verify password</h2>
<div className="form_block_two">
<div className="block">
<FormField
id={'password'}
formdata={this.state.formdata.password}
change={(element)=> this.updateForm(element)}
/>
</div>
<div className="block">
<FormField
id={'confirmPassword'}
formdata={this.state.formdata.confirmPassword}
change={(element)=> this.updateForm(element)}
/>
</div>
</div>
<div>
{ this.state.formError ?
<div className="error_label">
Please check your data
</div>
:null}
<button onClick={(event)=> this.submitForm(event)}>
Create an account
</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
export default connect()(Register);
So, I tried to add both:
mapDispatchToProps = (dispatch) => {
return {
registerTheUser: (submitData) => {dispatch(registerUser(submitData)) }
}
and
export default connect(mapDispatchToProps)(Register);
then changed:
this.props.dispatch(registerUser(dataToSubmit))
.then(response =>{
to
this.props.registerTheUser(dataToSubmit)
.then(response =>{
However, that also didn't work.
I am at a complete loss as to what it is I need to do. Is mapDispatchToProps() even the strategy I should be taking to fix this?
I can add more code if necessary.
EDIT, action registerUser():
export function registerUser(dataToSubmit){
const request = axios.post(`http://localhost:4444/users/create`,dataToSubmit)
.then(response => response.data);
return {
type: REGISTER_USER,
payload: request
}
}
mapDispatchToProps is the second argument to connect, the first argument is mapStateToProps
To supply just mapDispatchToProps, you must pass the first argument as null like
export default connect(null, mapDispatchToProps)(Register);
then use it like
this.props.registerTheUser(dataToSubmit)
.then(response =>{
Also the first way is correct, however your dispatch action isn't returning a promise and hence .then cannot be executed on it.
Make sure you use redux-thunk middleware and return a promise
const registerUser = (data) => {
return dispatch => {
return API.register('/url', data) // a return statement here for returning promise
}
}
This question has been asked several times in various forms over the years in the Tabulator GitHub repository. Here are a few instances:
https://github.com/olifolkerd/tabulator/issues/527, https://github.com/olifolkerd/tabulator/issues/1759
I'm looking for an example of how to achieve this using a dropdown menu of some form --- ideally as described in #1759 (dropdown with checkboxes) but another solution that would work for us is a "select" editor that adds/removes CSVs in the header filter when a value is selected/deselected (extending on the example provided in #527).
Hopefully someone with experience working with custom header filters / editors in tabulator can provide an example of a multi-select header filter dropdown, but if not, then I will post a JSFiddle link myself once I've got something that works.
Checkout: https://github.com/olifolkerd/tabulator/issues/527#issuecomment-850900451
Simple Answer by AkshayaBrianTauro
{
field: "book_name",
title: "Book Name",
headerFilterPlaceholder: " ",
headerFilter: 'select',
headerFilterFunc:"in",
headerFilterParams: {values:true, sortValuesList:"asc", multiselect:true}
},
Here is an example of a custom header filter for tabulator of 'select multiple' type. It can be converted to a dropdown style if desired using external sources such as Chosen or multiselect.js
(I recommend running the below Code Snippet in Full Page view).
const speciesTypes = ['Human', 'Android', 'Betazoid', 'Klingon', 'Ferengi', 'Tamarian'];
function multiSelectHeaderFilter(cell) {
var values = speciesTypes;
const filterFunc = (rowData) => {
return values.includes(rowData['species']);
}
const getSelectedValues = (multiSelect) => {
var result = [];
var options = multiSelect && multiSelect.options;
var opt;
for (var i = 0, iLen = options.length; i < iLen; i++) {
opt = options[i];
if (opt.selected) {
result.push(opt.value || opt.text);
}
}
return result;
}
const onChange = () => {
var editor = document.getElementById('speciesSelector');
values = getSelectedValues(editor);
console.log("values: " + values);
cell.getColumn().getTable().removeFilter(filterFunc);
cell.getColumn().getTable().addFilter(filterFunc);
}
var select = document.createElement("select");
select.multiple = "multiple";
select.id = 'speciesSelector';
select.class = "chosen-select";
select.style = 'width: 100%';
speciesTypes.forEach(species => {
select.innerHTML += "<option id='" + species + "' value='" + species + "' selected='selected'>" + species + "</option>";
});
cell.getColumn().getTable().addFilter(filterFunc);
select.addEventListener('change', onChange);
return select;
}
var table = new Tabulator("#tabulator", {
layout: "fitColumns",
data: [{
name: 'Geordi La Forge',
species: 'Human'
}, {
name: 'Dathon',
species: 'Tamarian'
}, {
name: 'Jean-Luc Picard',
species: 'Human'
}, {
name: 'Worf, son of Mogh',
species: 'Klingon'
}, {
name: 'Tasha Yarr',
species: 'Human'
}, {
name: 'Data',
species: 'Android'
}, {
name: 'Wesley Crusher',
species: 'Human'
}, {
name: 'Jalad',
species: 'Tamarian'
}, {
name: 'Lwaxana Troi',
species: 'Betazoid'
}, {
name: 'Temba',
species: 'Tamarian'
}, {
name: 'T\'Kuvma',
species: 'Klingon'
}, {
name: 'Lore',
species: 'Android'
}, {
name: 'Noonian Soongh',
species: 'Human'
}, {
name: 'Darmok',
species: 'Tamarian'
}, {
name: 'Reittan Grax',
species: 'Betazoid'
}, {
name: 'Quark',
species: 'Ferengi'
}],
headerSort: true,
columns: [{
title: 'Name',
field: 'name',
sorter: 'string'
}, {
title: 'Species',
field: 'species',
sorter: 'string',
headerFilter: multiSelectHeaderFilter,
headerFilterLiveFilter: false
}, ],
});
<html>
<head>
<link href="https://unpkg.com/tabulator-tables#4.5.3/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.5.3/dist/js/tabulator.min.js"></script>
</head>
<body>
<div id="tabulator"></div>
</body>
</html>
JSFiddle: https://jsfiddle.net/jjech/3th28pv0/
See my answer to Tabulator Multiple Filter in the same Column (show dropbox)
Extend as you see fit...
I dont think <select> support checkboxes as <option>'s, but it would be trivial to replace the <select> with a different style of "pulldown" that does.