How to make react-select searchable always show clear indicator - react-select

Actually, clear indicator only show when value has selected, i want to show up this when any value has type.
The reason is simple, easy clear current value search typed.

One solution to your problem is to use state to store the inputValue as value like the following code:
onChange = (option, { action }) => {
if (action === "clear") {
this.setState({
value: null
});
}
if (action === "select-option") {
this.setState({
value: option
});
}
};
onInputChange = (string, { action }) => {
if (action === "input-change") {
this.setState({
value: { value: string, label: string }
});
}
if (action === "menu-close") {
this.setState({
value: null
});
}
};
You can see with this piece of code:
if (action === "input-change") {
this.setState({
value: { value: string, label: string }
});
}
That you fake a value and as every time a value is set the clear function is enabled, it does the trick. You can find a live version of this code here.

const [value, setValue] = useState<any>(null)
const onChange = (option: any, { action } : {action: any}) => {
if (action === "clear") {
setValue(null)
}
if (action === "select-option") {
setValue(option)
}
};
const onInputChange = (string: any, { action }: {action: any}) => {
if (action === "input-change") {
setValue({ value: string, label: string });
}
if (action === "menu-close") {
setValue(null)
}
};

Related

Why is InterstitialAd not loaded after the first trigger?

I manage to get the first ad to show, but app crashed the next time I try to trigger an ad. And gives me this error: Error: InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown
In App.js
componentDidMount() {
const eventListener = interstitial.onAdEvent(type => {
if (type === AdEventType.LOADED) {
this.setState({
setLoaded: true,
});
}
});
interstitial.load();
eventListener();
}
showAds = () => {
interstitial.show();
// No advert ready to show yet
if (!this.state.loaded) {
console.log('null');
return null;
}
};
// This trigger is within another function
this.showAds();
I have a class component so I use ComponentDidMount instead of useEffect. Might that cause some troubles?
UPDATE:
this.state = {
loaded: false,
setLoaded: false,
Listener: null,
};
The above state is an attempt to redo
const [loaded, setLoaded] = useState(false);
constructor () {
super();
this.Listener=null
}
componentDidMount() {
this.Listener = interstitial.onAdEvent(type => {
if (type === AdEventType.LOADED) {
this.setState({
loaded: true,
});
}else if(type === AdEventType.CLOSED){
this.loadAd()
}
});
this.loadAd()
}
componentWillUnmount(){
if(this.Listener!==null){
this.Listener()
}
}
loadAd = () =>{
this.setState({
loaded: false,
});
interstitial.load();
}
showAds = () => {
if (!this.state.loaded) {
console.log('null');
return null;
}else{
interstitial.show();
}
};

select all checkbox inside vuetify select not working with composition API

I am trying to add a select all checkbox inside v-select. It's working fine with options API in vue js. But when working with composition API, couldn't find a way to workable it yet. My attempt is as below.
setup() {
const fruits = ['Apples', 'Apricots', 'Avocado', 'Bananas']
let selectedFruits = []
const likesAllFruit = computed(() => {
return selectedFruits.length === fruits.length
})
const likesSomeFruit = computed(() => {
return selectedFruits.length > 0 && !likesAllFruit.value
})
const icon = computed(() => {
if (likesAllFruit.value) return 'mdi-close-box'
if (likesSomeFruit.value) return 'mdi-minus-box'
return 'mdi-checkbox-blank-outline'
})
const toggle = async () => {
if (likesAllFruit.value) {
selectedFruits = []
} else {
selectedFruits = fruits.slice()
}
await nextTick()
}
return {
fruits,
selectedFruits,
likesAllFruit,
likesSomeFruit,
icon,
toggle,
}
},
I used https://vuetifyjs.com/en/components/selects/#append-and-prepend-item to build this as per in the document. Anyone knows where I was wrong this with in composition API?
(I am using vue js 2 version with composition API plugging)
Below way works.
setup() {
const fruits = ref([
{ text: 'Apples', value: 'Apples' },
{ text: 'Apricots', value: 'Apricots' },
{ text: 'Avocado', value: 'Avocado' },
{ text: 'Bananas', value: 'Bananas' },
])
let selectedFruits = ref([{}])
const likesAllFruit = computed(() => {
return selectedFruits.value.length === fruits.value.length
})
const likesSomeFruit = computed(() => {
return selectedFruits.value.length > 0 && !likesAllFruit.value
})
const icon = computed(() => {
if (likesAllFruit.value) return 'mdi-close-box'
if (likesSomeFruit.value) return 'mdi-minus-box'
return 'mdi-checkbox-blank-outline'
})
const toggle = async () => {
if (likesAllFruit.value) {
selectedFruits.value = []
} else {
selectedFruits.value = fruits.value.slice()
}
await nextTick()
}
return {
fruits,
selectedFruits,
likesAllFruit,
likesSomeFruit,
icon,
toggle,
}
},
Thanks all!!!

Server-side input validation with Quasar (Vue)

I'm looking for a reusable solution for server side input validation with Quasar Framework.
I use the q-input field. There are 2 props that can be used for the error output error and error-message. My server response on a validation error is a 400 response with this json
{
errors: { username: ['Username is to long.', 'User not valid'] },
title: 'One or more validation errors occurred.',
status: 400,
traceId: '80000005-0000-ff00-b63f-84710c7967bb'
}
I am currently using this logic, but I cannot move it to a mixin because I need access to the error field. The full example is available here codesandbox.io
<q-input
v-model="username"
filled
label="Username *"
:error-message="getErrorForField('username')"
:error="isErrorForField('username')"
/>
getErrorForField(field) {
if (!this.errors) {
return ''
}
const keys = Object.keys(this.errors)
const key = keys.find(
element => element.toLowerCase() === field.toLowerCase()
)
if (this.errors[key]) {
return this.errors[key].join('\r\n')
}
},
isErrorForField(field) {
if (!this.errors) {
return false
}
const keys = Object.keys(this.errors)
const key = keys.find(
element => element.toLowerCase() === field.toLowerCase()
)
if (this.errors[key]) {
return true
}
}
I have found a solution with the new vue3 composition-api. I now have a reusable logic.
MyComponent.vue
<template>
<q-input
v-model="username"
filled
label="Username *"
:error-message="getErrorForField('username')"
:error="isErrorForField('username')"
/>
</template>
<script>
import { validationHelper } from 'src/helper/validationHelper'
export default {
name: 'MyComponent',
setup () {
const { showValidationError, setValidationErrors, getValidationErrors, hasValidationErrors } = validationHelper()
return {
showValidationError,
setValidationErrors,
getValidationErrors,
hasValidationErrors
}
},
methods: {
async add () {
try {
//axios request
} catch (error) {
this.setValidationErrors(error.response.data.errors)
this.showValidationError()
}
}
}
}
</script>
validationHelper.js
import { ref } from '#vue/composition-api'
export function validationHelper () {
const errors = ref([])
function getValidationErrorMessages (field) {
if (!errors.value) {
return []
}
const keys = Object.keys(errors.value)
const key = keys.find(element => element.toLowerCase() === field.toLowerCase())
if (errors.value[key]) {
return errors.value[key]
}
return []
}
function getValidationErrors (field) {
const errors = getValidationErrorMessages(field)
if (errors.length !== 0) {
return errors.join('\r\n')
}
return ''
}
function hasValidationErrors (field) {
if (getValidationErrorMessages(field).length !== 0) {
return true
}
return false
}
function setValidationErrors (payload) {
errors.value = payload
}
function showValidationError () {
this.$q.notify({
type: 'negative',
message: 'Validation failure',
caption: 'please check the inputs'
})
}
return {
showValidationError,
setValidationErrors,
getValidationErrors,
hasValidationErrors
}
}

Sending field input to firebase from state

I'm currently working on app that has ability to add new tasks, assign them to others and choose due date.
I'd like to start sending the assignee and due date of the task to my firebase.
This is my dropdowncomponent:
class DropdownComponent extends Component {
constructor(props){
super(props);
this.state = {
assignee: '',
data: [{
value: 'apple',
}, {
value: 'lemon',
}, {
value: 'orange',
}, {
value: 'banana',
}, {
value: 'watermelon',
}],
value: ''
}
}
handleAssigneePicked = value => {
this.setState({ assignee: value })
console.log("Assignee " + value)
};
render() {
return (
<Dropdown
data={this.state.data}
value={this.state.assignee}
onChangeText={this.handleAssigneePicked}
/>
);
}
}
And this is how I render datepicker
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked}
onCancel={this.hideDateTimePicker}
/>
handleDatePicked = date => {
console.log("A date has been picked: ", date);
this.hideDateTimePicker();
this.setState({ selectedDate: moment().format('D MMM DD YYYY HH:MM')})
};
When I choose an item from dropdown, it also console logs the corresponding value, meaning the state changed, no issues there.
However, if i'm trying to send that information to firebase, using code below:
const SaveNewTask = (name, body) => {
const { currentUser } = firebase.auth();
// eslint-disable-next-line no-undef
// eslint-disable-next-line no-unused-expressions
!!name && !!body
?
firebase
.database()
.ref(`/users/${currentUser.uid}/tasks`)
.push({
name, body, assignee, selectedDate, timestamp: Date.now(), completed: false, archived: false
})
// eslint-disable-next-line no-undef
: alert('All fields are required.');
};
But I'm getting can't find variable: assignee and selectedDate, can I get some help with this? I must be missing something little.
Looks like you forgot to pass these params to action
const SaveNewTask = (name, body, assignee, selectedDate) => {
const { currentUser } = firebase.auth();
!_.isEmpty(name) && !_.isEmpty(body) && !_.isEmpty(assignee) && selectedDate != undefined
?
firebase
.database()
.ref(`/users/${currentUser.uid}/tasks`)
.push({
name, body, assignee, selectedDate, timestamp: Date.now(), completed: false, archived: false
})
: alert('All fields are required.');
};
you can use _.isEmpty() by lodash

Relay Moder - Pagination

I am already working on Pagination.
I used PaginationContainer for that. It work’s but no way what I am looking for.
I got button next which call props.relay.loadMore(2) function. So when I click on this button it will call query and add me 2 more items to list. It works like load more. But I would like instead of add these two new items to list, replace the old item with new.
I try to use this getFragmentVariables for modifying variables for reading from the store but it’s not working.
Have somebody Idea or implemented something similar before?
class QueuesBookingsList extends Component {
props: Props;
handleLoadMore = () => {
const { hasMore, isLoading, loadMore } = this.props.relay;
console.log('hasMore', hasMore());
if (!hasMore() || isLoading()) {
return;
}
this.setState({ isLoading });
loadMore(1, () => {
this.setState({ isLoading: false });
});
};
getItems = () => {
const edges = idx(this.props, _ => _.data.queuesBookings.edges) || [];
return edges.map(edge => edge && edge.node);
};
getItemUrl = ({ bid }: { bid: number }) => getDetailUrlWithId(BOOKING, bid);
render() {
return (
<div>
<button onClick={this.handleLoadMore}>TEST</button>
<GenericList
displayValue={'bid'}
items={this.getItems()}
itemUrl={this.getItemUrl}
emptyText="No matching booking found"
/>
</div>
);
}
}
export default createPaginationContainer(
QueuesBookingsList,
{
data: graphql`
fragment QueuesBookingsList_data on RootQuery {
queuesBookings(first: $count, after: $after, queueId: $queueId)
#connection(
key: "QueuesBookingsList_queuesBookings"
filters: ["queueId"]
) {
edges {
cursor
node {
id
bid
url
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
`,
},
{
direction: 'forward',
query: graphql`
query QueuesBookingsListQuery(
$count: Int!
$after: String
$queueId: ID
) {
...QueuesBookingsList_data
}
`,
getConnectionFromProps(props) {
return props.data && props.data.queuesBookings;
},
getFragmentVariables(prevVars, totalCount) {
console.log({ prevVars });
return {
...prevVars,
count: totalCount,
};
},
getVariables(props, variables, fragmentVariables) {
return {
count: variables.count,
after: variables.cursor,
queueId: fragmentVariables.queueId,
};
},
},
);
As I figure out, there are two solutions, use refechConnection method for Pagination Container or use Refech Container.