React-leaflet - add/remove style to CircleMarker on click - react-leaflet

I am working with react-leaflet to show some data points as circles on a map. I am trying to add a click function to <CircleMarker> so when a circle is clicked, it will add a className "active" and when another circle is clicked, it will remove the "active" class from the previously clicked circle and add the "active" class to the newly clicked circle.
I have a handleClick function that gets the clicked element and setState on the "selected" property with that element. I thought I could just do something like className={ selected.id === data.id ? "active" : "inactive" } for each <CircleMarker>, but it is not switching to the "active" class but stays "inactive" on every click. I checked my css and "active" class works, and the click function is properly firing. Please help!! Here is the simplified version of my code:
class MapComponent extends Component {
constructor(props){
super(props)
this.state = {
selected: {}
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(data, e) {
this.setState({ selected: data })
}
render(){
const { myData } = this.props;
const { selected } = this.state;
return (
<div>
<Map center="xxxxx" zoom=11>
<TileLayer url="xxxxx" attribution="xxxxx" />
{
myData && myData.values.map(data => {
return (
<CircleMarker
className={ selected.id === data.id ? "active" : "inactive" }
key={ data.id }
center={ new L.latLng(data.latitude, data.longitude) }
radius=10
color="red"
value={ data.id }
onClick={ (e) => this.handleCircleClick(data, e) }
>
</CircleMarker>
)
})
}
</Map>
</div>
)
}
}

I finally figured out. It's not so pretty, but I had to manipulate the DOMTokenList manually inside my handleClick() method, using something like event.target._path.classList.replace():
handleClick(data, e) {
this.setState({ selected: data })
if(e.target._path.classList.contains("inactive")){
e.target._path.classList.replace("inactive", "active")
$(event.target).siblings().removeClass("active")
$(event.target).siblings().addClass("inactive")
}
}
I still don't know why I can't just change the className by doing className={ selected.id === data.id ? "active" : "inactive" } on the react-leaflet's <CircleMarker> component though.

Related

Vuejs/Posgres - When clicked on button I want to save a value in db postgresql

Hi so I have a view where I have a button , When it's clicked I want a value to be saved in the db . What I get now is nothing like I click on button but nothing happens .
Here's the code I have :
<a-button type="primary" class="mb-4 text-center mr-1 float-right" #click="onSubmit">Confirm</a-button>
in my script I have:
setup(){
const onSubmit = () => {
axios.post("/insertstatut/"+876,"added").then((res)=>{
message.success(`statut ajouté`)
router.push({
path:'/cand',
}).catch(error => {
console.log('error', error);
})
} ,
)
}
}
Please if u have any idea what I should do , do share thank you.
you are using composition api feature setup in your vue code,
you need to return the methods or properties u wish to use in in your template.
setup () {
return {
onSubmit: () => {}, //some method u want to use later in template ,
show: false, // or some property
}
}
this is how your component should look
<template>
<a-button
type="primary"
class="mb-4
text-center
mr-1float-right"
#click="onSubmit"
>
Confirm
</a-button>
</template>
<script>
import AButton from './button-path/AButton.vue'
import axios from 'axios'
export default {
componets: { AButton },
setup() {
const onSubmit = () => {
axios.post('/insertstatut/' + 876, 'added').then((res) => {
message.success(`statut ajouté`)
router
.push({
path: '/cand',
})
.catch((error) => {
console.log('error', error)
})
})
}
// Expose your constants/methods/functions
return {
onSubmit,
}
},
}
</script>

How to pass data dynamic child component in react

I am creating dynamic child components for a table.
Parent Component
class SimpleView extends Component {
constructor(props) {
super(props);
this.onAutoChange = this.onAutoChange.bind(this);
this.state = {
columns: this.createcolumns(clone(this.props.tableInfo.columns)),
dataList: this.props.data,
result: []
};
}
createcolumns(columns) {
const editColumnRender = (text, record, index) =>
<AssingCell
index={index}
columnsKey={columns[3].key}
onAutoChange={this.onAutoChange}
/>;
columns[3].render = editColumnRender;
return columns;
}
onAutoChange(value){
this.props.fetchDrivers('',value);
}
componentWillReceiveProps(nextProps){
if(nextProps.driversData && nextProps.driversData.message === 'SUCCESS' && i<1)
{
this.setState({driversResult: nextProps.driversData.data});
i=i+1;
}
}
render() {
const { columns, dataList, loading } = this.state;
return (
<TableWrapper
columns={columns}
dataSource={dataList}
/>
);
}
}
Here is a child component named AssingCell. There is a modal button inside the button. There is also one autocomplete in Modal. This.props.onAutoChange is called during every call. In this section, data is fetched from the server. How can I send this data to the child component?
Or how else can I do this?

How can I use props to auto-populate editable redux-form fields in React?

I'm new to React so I've tried to show as much code as possible here to hopefully figure this out! Basically I just want to fill form fields with properties from an object that I fetched from another API. The object is stored in the autoFill reducer. For example, I would like to fill an input with autoFill.volumeInfo.title, where the user can change the value before submitting if they want.
I used mapDispatchtoProps from the autoFill action creator, but this.props.autoFill is still appearing as undefined in the FillForm component. I'm also confused about how to then use props again to submit the form. Thanks!
My reducer:
import { AUTO_FILL } from '../actions/index';
export default function(state = null, action) {
switch(action.type) {
case AUTO_FILL:
return action.payload;
}
return state;
}
Action creator:
export const AUTO_FILL = 'AUTO_FILL';
export function autoFill(data) {
return {
type: AUTO_FILL,
payload: data
}
}
Calling the autoFill action creator:
class SelectBook extends Component {
render() {
return (
....
<button
className="btn btn-primary"
onClick={() => this.props.autoFill(this.props.result)}>
Next
</button>
);
}
}
....
function mapDispatchToProps(dispatch) {
return bindActionCreators({ autoFill }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(SelectBook);
And here is the actual Form where the issues lie:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { reduxForm } from 'redux-form';
import { createBook } from '../actions/index;
class FillForm extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
}
onSubmit(props) {
this.props.createBook(props)
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
const { fields: { title }, handleSubmit } = this.props;
return (
<form {...initialValues} onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<input type="text" className="form-control" name="title" {...title} />
<button type="submit">Submit</button>
</form>
)
}
export default reduxForm({
form: 'AutoForm',
fields: ['title']
},
state => ({
initialValues: {
title: state.autoFill.volumeInfo.title
}
}), {createBook})(FillForm)
I think you're mixing up connect and reduxForm decorators in the actual form component. Currently your code looks like this (annotations added by me):
export default reduxForm({
// redux form options
form: 'AutoForm',
fields: ['title']
},
// is this supposed to be mapStateToProps?
state => ({
initialValues: {
title: state.autoFill.volumeInfo.title
}
}),
/// and is this mapDispatchToProps?
{createBook})(FillForm)
If this is the case, then the fix should be as simple as using the connect decorator as it should be (I also recommend separating this connect props to their own variables to minimize confusions like this):
const mapStateToProps = state => ({
initialValues: {
title: state.autoFill.volumeInfo.title
}
})
const mapDispatchToProps = { createBook }
export default connect(mapStateToProps, mapDispatchToProps)(
reduxForm({ form: 'AutoForm', fields: ['title'] })(FillForm)
)
Hope this helps!

Pagination in Wizard Redux Form in Stateless Component

i'm new to react-redux and i want some help with a task. As you can see in the redux-form documentation for a wizard for the author uses a stateful main component to create next and previous page functions using setState but in our project we must not use class base components
class WizardForm extends Component {
constructor(props) {
super(props)
this.nextPage = this.nextPage.bind(this)
this.previousPage = this.previousPage.bind(this)
this.state = {
page: 1
}
}
nextPage() {
this.setState({ page: this.state.page + 1 })
}
previousPage() {
this.setState({ page: this.state.page - 1 })
}
render() {
const { onSubmit } = this.props
const { page } = this.state
return (<div>
{page === 1 && <WizardFormFirstPage onSubmit={this.nextPage}/>}
{page === 2 && <WizardFormSecondPage previousPage={this.previousPage} onSubmit={this.nextPage}/>}
{page === 3 && <WizardFormThirdPage previousPage={this.previousPage} onSubmit={onSubmit}/>}
</div>
)
}
}
How to make this transformation correctly?

Dynamically include files (components) and dynamically inject those components

Looking around the next I could not find the answer: How do I dynamicly include a file, based on prop change per say: here some sudo code to intrastate what I'm trying to do!
class Test extends React.Component {
constructor(props){
super(props)
this.state = { componentIncluded: false }
includeFile() {
require(this.props.componetFileDir) // e.g. ./file/dir/comp.js
this.setState({ componentIncluded: true });
}
render() {
return(
<div className="card">
<button onClick={this.includeFile}> Load File </button>
{ this.state.componentIncluded &&
<this.state.customComponent />
}
</div>
)
}
}
so this.props.componetFileDir has access to the file dir, but I need to dynamically include it, and can't really do require() as its seems to running before the action onClick get called. Any help would be great.
Em, Your code looks a bit wrong to me. So I created a separate demo for dynamic inject components.
While in different situation you can use different React lifecycle functions to inject your component. Like componentWillReceiveProps or componentWillUpdate.
componentDidMount() {
// dynamically inject a Button component.
System.import('../../../components/Button')
.then((component) => {
// update the state to render the component.
this.setState({
component: component.default,
});
});
}
render() {
let Button = null;
if (this.state.component !== null) {
Button = this.state.component;
}
return (
<div>
{ this.state.component !== null ? <Button>OK</Button> : false }
</div>
);
}
After you edited your code, it should be something similar to below:
class Test extends React.Component {
constructor(props){
super(props)
this.state = { customComponent: null }
this.includeFile = this.includeFile.bind(this);
}
includeFile() {
System.import(this.props.componetFileDir)
.then((component) => {
this.setState({ customComponent: component.default });
});
}
render() {
return(
<div className="card">
<button onClick={this.includeFile}> Load File </button>
{
this.state.customComponent
}
</div>
)
}
}