using tcomb form native in react native - react-native

I am using tcomb to build a form in react-native, a field in my form is birthDate: t.maybe(t.Date), but it appears to have no style
const formRegistration = t.struct({
// other fields
birthDate: t.maybe(t.Date)
});
I have also added config down the options:
const options = {
fields : {
birthDate: {
label: 'Birth Date',
mode: 'date',
config: {
format: (date) => myFormatFunction('DD MM YYYY', date),
dialogMode: 'spinner'
}
}
}
}
};

Looking at this: https://github.com/gcanti/tcomb-form-native/blob/master/lib/stylesheets/bootstrap.js
The style for the date is in dateValue at line 196
so this is what I did to style it according to the need:
const Form = t.form.Form;
Form.stylesheet.dateValue.normal.borderColor = '#d0d2d3';
Form.stylesheet.dateValue.normal.backgroundColor = '#f0f1f1';
Form.stylesheet.dateValue.normal.borderWidth = 1;
you follow the same way to style other key parts in tcomb (e.g: labels: Form.stylesheet.controlLabel.normal.fontSize = 14;)

Related

vue-i18n: Wrong date format for e.g. Norwegian

I'm using vue-i18n (version 8.24.2) in my app, and everything works as expected except when rendering dates using locale = nb-NO (Norwegian). Expected format: dd.MM.yyyy. Actual format: MM/dd/yyyy. When switching locale to German, which is using the same date format as Norwegian, correct date format is applied.
This open issue would probably solve my issue:
https://github.com/kazupon/vue-i18n/issues/625
I've spent a couple of hours investigating this issue, but I'm currently stuck, hence any help will be highly appreciated.
My i18n.ts (I left out config for languages not related to this issue)
import Vue from "vue";
import VueI18n from "vue-i18n";
enum Locales {
NO = "nb-NO"
}
const LOCALES = [
{ value: Locales.NO, caption: "Norsk" }
];
import nb_NO from "./locales/nb-NO.json";
export const messages = {
[Locales.NO]: nb_NO
};
const defaultLocale = Locales.NO;
const dateTimeFormats = {
"nb-NO": {
short: {
year: "numeric",
month: "2-digit",
day: "2-digit",
},
long: {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: false,
},
},
} as VueI18n.DateTimeFormats;
Vue.use(VueI18n);
// Create VueI18n instance with options
const i18n = new VueI18n({
locale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE || defaultLocale,
fallbackLocale: defaultLocale,
messages,
dateTimeFormats: dateTimeFormats,
silentTranslationWarn: true,
});
const translate = (key: string): string => {
if (!key) {
return "";
}
return i18n.t(key) as string;
};
export { i18n, translate }; //export above method
vue-i18n simply forwards the date localization to Intl.DateTimeFormat(locale).format(date).
It seems the result is only incorrect in Chrome as of v92 (Issue 1233509). This bug is fixed in Chrome Canary v94.
As a workaround, you can modify the vue-i18n instance's _dateTimeFormatters to use the Danish (da) locale's formatter for nb-NO:
const i18n = new VueI18n({/*...*/});
i18n._dateTimeFormatters[Locales.NO + '__short'] =
new Intl.DateTimeFormat('da', dateTimeFormats[Locales.NO].short);
i18n._dateTimeFormatters[Locales.NO + '__long'] =
new Intl.DateTimeFormat('da', dateTimeFormats[Locales.NO].long);
demo

Add Custom Event on dynamic Component Vue.js

I've created a dynamic Custom Component and i wanna register/add a custom event on this component,like:
<SelectContactRowComponent #customevent="custommethod()"></SelectContactRowComponent
This is my dynamic customcomponent code:
var RowComponent = Vue.extend(SelectContactRowComponent);
var instance = new RowComponent( {propsData: {
item_data: {'lastname': '', 'firstname' : '', 'email' : '', 'telephone' : ''},
isDOMadd : true,
data_source_url : this.data_source_url,
id: this.id,
id_name: this.id_name,
morph_class_id: this.morph_class,
}
}).$mount();
You should do that in your emit option of the SelectContactRowComponent
const app = Vue.createApp({})
app.component('select-contact-row-component', {
emits: ['customevent']
})
Then you can emit it within the SelectContactRowComponent methods, or lifecycle hooks depending on your logic
this.$emit('customevent', { payload })

fireEvent on SegmentedControlIOS

I am using react-native-testing-library - https://callstack.github.io/react-native-testing-library/docs/getting-started
I have a <SegmentedControlIOS> - https://facebook.github.io/react-native/docs/segmentedcontrolios
I want to pres the first segment. I am doing this:
const testID = "SegmentedControl";
const stub = jest.fn();
const values = [{ label: "foo" }];
const { getByTestId } = render(
<SegmentedControlIOS values={['foo', 'bar']} onChange={stub} testID={testID} />
);
expect(() => {
getByTestId(testID);
}).not.toThrow();
fireEvent(getByTestId(testID), "change ", {
nativeEvent: {
value: values[0],
selectedSegmentIndex: 0,
},
});
However I get the error:
No handler function found for event: "change "
Screenshot below. Anyone know how to press different segments in <SegmentedControlIOS>?
fireEvent(element: ReactTestInstance, eventName: string, ...data:
Array): void
The change function is located in the fireEvent object. Here's how to use it:
Version 5 or later:
fireEvent.change(getByTestId(testID), { target: { value: values[0],selectedSegmentIndex: 0 } });
Version 5 or before:
const input = getByTestId(testID);
input.value = values[0];
input.selectedSegmentIndex = 0;
fireEvent.change(input);
If you want to check the onChange function of SegmentedControlIOS,
using fireEvent with native events that aren't already aliased by the fireEvent api.
// you can omit the `on` prefix
fireEvent(getByTestId(testID), 'onChange');
A solution was posted here, I didn't try it yet, but it looks more right I think - https://github.com/callstack/react-native-testing-library/issues/220#issuecomment-541067962
import React from "react";
import { SegmentedControlIOS } from "react-native";
import { fireEvent, render } from "react-native-testing-library";
const testID = "SegmentedControl";
const stub = jest.fn();
const values = [{ label: "foo" }];
const { getByTestId } = render(
<SegmentedControlIOS
values={["foo", "bar"]}
onChange={stub}
testID={testID}
/>,
);
it("sends events", () => {
fireEvent(getByTestId(testID), "onChange", {
nativeEvent: {
value: values[0],
selectedSegmentIndex: 0,
},
});
});

Vue template fires more than once when used, i think i need a unique key somewhere

I am trying to implement font-awesome-picker to a website that i am making using vue2/php/mysql, but within standard js scripting, so no imports, .vue etc.
The script i am trying to add is taken from here: https://github.com/laistomazz/font-awesome-picker
The problem that i am facing is that i have 3 columns that have a title and an icon picker next it, that will allow the user to select 1 icon for each title. It is kinda working well...but if the same icon is used in 2 different columns then any time the user clicks again any of the 2 icons both instances of the picker will fire up, thus showing 2 popups. I need to somehow make them unique.
I've tried using
:key="list.id"
or
v-for="icon in icons" :icon:icon :key="icon"
but nothing worked. Somehow i have to separate all the instances (i think) so they are unique.
This is the template code:
Vue.component('font-awesome-picker', {
template: ' <div><div class="iconPicker__header"><input type="text" class="form-control" :placeholder="searchPlaceholder" #keyup="filterIcons($event)" #blur="resetNew" #keydown.esc="resetNew"></div><div class="iconPicker__body"><div class="iconPicker__icons"><i :class="\'fa \'+icon"></i></div></div></div>',
name: 'fontAwesomePicker',
props: ['seachbox','parentdata'],
data () {
return {
selected: '',
icons,
listobj: {
type: Object
}
};
},
computed: {
searchPlaceholder () {
return this.seachbox || 'search box';
},
},
methods: {
resetNew () {
vm.addNewTo = null;
},
getIcon (icon) {
this.selected = icon;
this.getContent(this.selected);
},
getContent (icon) {
const iconContent = window
.getComputedStyle(document.querySelector(`.fa.${icon}`), ':before')
.getPropertyValue('content');
this.convert(iconContent);
},
convert (value) {
const newValue = value
.charCodeAt(1)
.toString(10)
.replace(/\D/g, '');
let hexValue = Number(newValue).toString(16);
while (hexValue.length < 4) {
hexValue = `0${hexValue}`;
}
this.selecticon(hexValue.toUpperCase());
},
selecticon (value) {
this.listobj = this.$props.parentdata;
const result = {
className: this.selected,
cssValue: value,
listobj: this.listobj
};
this.$emit('selecticon', result);
},
filterIcons (event) {
const search = event.target.value.trim();
let filter = [];
if (search.length > 3) {
filter = icons.filter((item) => {
const regex = new RegExp(search, 'gi');
return item.match(regex);
});
}else{
this.icons = icons;
}
if (filter.length > 0) {
this.icons = filter;
}
}
},
});
I've setup a fiddle with the problem here:
https://jsfiddle.net/3yxk1ahb/1/
Just pick the same icon in both cases, and then click any of the icons again. You'll see that the popups opens for both columns.
How can i separate the pickers ?
problem is in your #click and v-show
you should use list.id instead of list.icon (i.e #click="addNewTo = list.id")
working fiddle https://jsfiddle.net/q513mhwt/

fetch data using react native sectionList

I'm working with firestore and i'm trying to fetch the data into my SectionList component. I want the sections to be broken up by the dates in my firestore data. For instance, if a user has booked a date of Sep 12th then the section header should show the previous Sunday (in this case Sep 9th)for the given date. My issue is I keep getting error "sectionlist length undefined". I understand it needs to be an array. How do I place the info from the array from firestore into the section 'data' and 'title' props.
I've already pulled data from the collection and placed it into this.state. I need to plug the info from dates into sections of my sectionlist component.
onCollectionUpdate = (querySnapshot) => {
var history = this.state.history;
let that = this;
querySnapshot.forEach((doc) => {
const { date, displayName, hours, image} = doc.data();
history.push({
key: doc.id,
date: doc.data().date,
displayName: doc.data().displayName,
hours: doc.data().hours,
image: doc.data().image,
});
});
that.setState({
history,
sections,
loading: false,
});
}
I was able to get the list to populate but each item is in its own view. I'm working on a way to get all dates within the same week to fall under the Sunday of that week view group. This is my function which i know i need to manipulate the way the array is pushed.
onCollectionUpdate = (querySnapshot) => {
// make copy of history object
let that = this;
let history = this.state.history;
let sectionExist = false;
//let history = JSON.stringify(JSON.parse(this.state.history);
querySnapshot.forEach((doc) => {
// find last sunday
var dates = moment(doc.data().date);
var weekOf = dates.startOf('week').valueOf();
var weekOfFormat = moment(weekOf).format('MMM Do')
console.log(doc);
history.push({
title: weekOfFormat,
data: [{
key: doc.id,
date: doc.data().date,
displayName: doc.data().displayName,
hours: doc.data().hours,
image: doc.data().image,
}]
});
});
that.setState({
history,
loading: false,
});
}
I think your misunderstanding is, that SectionList does not need an array of items. It needs an array of sections, where each section has an array of items (data).
Your code should look something like this:
onCollectionUpdate = (querySnapshot) => {
// make copy of history object
let history = JSON.stringify(JSON.parse(this.state.history);
querySnapshot.forEach((doc) => {
// find last sunday
let now = new Date(doc.data().date);
let today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
let lastSunday = new Date(today.setDate(today.getDate()-today.getDay()));
let lastSundayString = convertDateToMyStringFormat(lastSunday);
// check if section with this date as section title exists and push to that data if so
let sectionExists = false;
for(let i = 0; i < history.length; i++;) {
if(history[i].title === lastSundayString){
sectionExists = true;
history[i].data.push({
key: doc.id,
date: doc.data().date,
displayName: doc.data().displayName,
hours: doc.data().hours,
image: doc.data().image,
});
break;
}
}
// add new section if no such section found
if(!sectionExists){
history.push({
title: lastSundayString,
data: [{
key: doc.id,
date: doc.data().date,
displayName: doc.data().displayName,
hours: doc.data().hours,
image: doc.data().image,
}]
});
}
});
this.setState({
history,
loading: false,
});
}
You will have to implement your own convertDateToMyStringFormat function, to get a title string out of your Javascript Date object.