How can I translate yup errors with next18-next since it should be server-side rendered?
Is it possible to use placeholders in next18-next translations strings?
It was pretty simple to solve this.
validate.ts:
export const setValidationTranslations = (t: TFunction) => {
const required = t("required");
const minString = t("min_string");
const maxString = t("max_string");
const emailValid = t("email_valid");
const minNumber = t("min_number");
const maxNumber = t("max_number");
setLocale({
mixed: {
required: required,
},
string: {
min: minString,
max: maxString,
email: emailValid,
},
number: {
min: minNumber,
max: maxNumber,
},
});
};
export const schema = () => {
return object().shape({
email: string().email().required(),
password: string().required().min(6),
});
};
Page.tsx:
import {
setValidationTranslations,
schema,
} from "./validate";
function Page() {
const { t } = useTranslation("common");
setValidationTranslations(t);
...
}
common.json with default yup texts:
{
"required": "${path} is a required field",
"email_valid": "${path} must be a valid email",
"min_string": "${path} must be at least ${min} characters",
"max_string": "${path} must be at most ${max} characters",
"min_number": "${path} must be greater than or equal to ${min}",
"max_number": "${path} must be less than or equal to ${max}"
}
Related
When i am trying to implement Apple Pay using #stripe/stripe-react-native then is not working showing some hook call , Code & Error showing below:
import { StripeProvider, useApplePay} from '#stripe/stripe-react-native';
const { presentApplePay, confirmApplePayPayment } = useApplePay();
export default class App (){
handlePayPress = async () => {
const {error, paymentMethod} = await presentApplePay({
cartItems: [
{
label: 'payment label',
amount: '50', // amount as string
type: 'final',
},
],
country: 'US', // enter any country code supported by stripe,
currency: 'USD', // enter any currency supported by stripe,
});
if (error) {
Alert.alert(error.code, error.message);
} else {
const {error: confirmApplePayError} = await confirmApplePayPayment(
clientSecret,
);
confirmApplePayPayment(clientSecret);
if (confirmApplePayError) {
Alert.alert(confirmApplePayError.code, confirmApplePayError.message);
} else {
Alert.alert('Success', 'The payment was confirmed successfully!');
}
}
};
...
...
}
You can create a seperate functional component for that and call in your class component like this
export default class App (){
render() {
return(
<ApplePayFunction data={'your data here'}/>
);
}
}
export default function ApplePayFunction(props) {
const { presentApplePay, confirmApplePayPayment } = useApplePay();
const handlePayPress = async () => {
const { error, paymentMethod } = await presentApplePay({
cartItems: [
{
label: "payment label",
amount: "50", // amount as string
type: "final",
},
],
country: "US", // enter any country code supported by stripe,
currency: "USD", // enter any currency supported by stripe,
});
if (error) {
Alert.alert(error.code, error.message);
} else {
const { error: confirmApplePayError } = await confirmApplePayPayment(
clientSecret
);
confirmApplePayPayment(clientSecret);
if (confirmApplePayError) {
Alert.alert(confirmApplePayError.code, confirmApplePayError.message);
} else {
Alert.alert("Success", "The payment was confirmed successfully!");
}
}
};
// Return UI Views below
return null;
}
Hooks must always be called inside functional components. Code refactor for reference.
import { StripeProvider, useApplePay } from "#stripe/stripe-react-native";
export default function App() {
const { presentApplePay, confirmApplePayPayment } = useApplePay();
const handlePayPress = async () => {
const { error, paymentMethod } = await presentApplePay({
cartItems: [
{
label: "payment label",
amount: "50", // amount as string
type: "final",
},
],
country: "US", // enter any country code supported by stripe,
currency: "USD", // enter any currency supported by stripe,
});
if (error) {
Alert.alert(error.code, error.message);
} else {
const { error: confirmApplePayError } = await confirmApplePayPayment(
clientSecret
);
confirmApplePayPayment(clientSecret);
if (confirmApplePayError) {
Alert.alert(confirmApplePayError.code, confirmApplePayError.message);
} else {
Alert.alert("Success", "The payment was confirmed successfully!");
}
}
};
// Return UI Views below
return null;
}
I am using exceljs library in react application.
I am inserting my company logo on top of my data (and their headers), but my code just inserts it on top of everything.
const imageId2 = workbook.addImage({
base64: myBase64Image,
extension: 'png',
});
worksheet.addImage(imageId2, 'A1:D3');
worksheet.mergeCells('A1:D3');
worksheet.getRow(1).font = {
name: 'Arial Black',
bold: true,
};
worksheet.columns = rowHeader;
worksheet.addRows(dataTableRows);
workbook.xlsx.writeBuffer().then(data => {
const blob = new Blob([data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
Alternatively, I could do this hack, but I don't know how to do this dynamically:
worksheet.addRow([rowHeader[0].key, rowHeader[1].key, rowHeader[2].key]);
https://github.com/exceljs/exceljs/issues/433
row headers looks like this:
const rowHeader = [
{ key: 'xxx' },
{ key: 'adsff' },
{ key: 'ff' },
{ key: 'ffff' },
{ key: 'sdfasdf' },
{ key: 'fasdfads' },
{ key: 'fasdfasdf' },
{ key: 'fasdfadf' },
{ key: 'fasdfawsdft' },
];
const imageId2 = workbook.addImage({
base64: myBase64Image,
extension: 'png',
});
worksheet.addImage(imageId2, 'A1:D3');
worksheet.mergeCells('A1:D3');
worksheet.addRow({});
const col: string[] = [];
rowHeader.forEach(header => {
col.push(header.key);
});
const columnHeaders: string[] = Object.values(col);
worksheet.getRow(5).values = columnHeaders;
worksheet.getRow(5).font = {
name: 'Arial Black',
bold: true,
};
worksheet.columns = rowHeader;
worksheet.addRows(dataTableRows);
workbook.xlsx.writeBuffer().then(data => {
const blob = new Blob([data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
const a = window.document.createElement('a');
const downloadUrl = window.URL.createObjectURL(blob);
a.href = downloadUrl;
a.download = `${fileName}.xlsx`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(downloadUrl);
});
Can't get errors from resolver using react-hook-form custom resolvers. Trying to validate some fields dynamically. But if I submit form I can get errors fields
export const customResolver = (parameters) => {
return (values, _context, { fields, names }) => {
const transformedParameters = transformParameters(parameters);
const paramsIds = getParamsIds(transformedParameters);
const { name, value } = Object.values(fields)[0];
let errors = {};
if (names && names[0].length <= 3) {
// Validate single field
const textRequired = transformedParameters
.find(({ id }) => id === name)
.values.find(({ name: valueName }) => value === valueName).textRequired;
if (textRequired && !values[`${names} commentary`]) {
errors = {
[`${names} commentary`]: {
type: "required",
message: "Поле необходимо заполнить!",
},
};
}
} else {
// Validate onSubmit method
errors = Object.entries(values).reduce((acc, [id, fieldValue]) => {
if (paramsIds.includes(id) && !fieldValue) {
return {
...acc,
[id]: { type: "required", message: "Поле необходимо заполнить!" },
};
}
return acc;
}, {});
}
return { values, errors };
};
};
What did I do wrong?
i have a comments connection in a mutation, this is the query:
export default mutationFromQuery(graphql`
mutation AddBookMutation($input: AddBookInput! $count: Int $cursor: String ) {
addBook(input: $input) {
book {
__typename
cursor
node {
id
title
owner
createdAt
comments(first: $count, after: $cursor)
#connection(key: "BookComments_comments", filters: []) {
__typename
edges {
node {
id
}
}
}
}
}
}
}
`)
This is how i did my optimisticUpdater that don't work:
optimisticUpdater: (store) => {
const userProxy = store.get(viewerId)
const owner = userProxy.getValue('username')
const id = uuidv1();
const book = store.create(id, 'Book');
book.setValue(id, 'id');
book.setValue(bookTitle, 'title');
book.setValue(owner, 'owner');
book.setValue(Date.now(), 'createdAt');
const comments = store.create(uuidv1(), 'comments')
comments.setLinkedRecords([], 'edges')
const pageInfo = store.create(uuidv1(), 'pageInfo')
pageInfo.setValue(null, 'endCursor')
pageInfo.setValue(false, 'hasNextPage')
pageInfo.setValue(false, 'hasPreviousPage')
pageInfo.setValue(null, 'startCursor')
comments.setLinkedRecord(pageInfo, 'pageInfo')
book.setLinkedRecord(comments, 'comments')
const bookEdge = store.create(uuidv1(), 'BookEdge');
bookEdge.setLinkedRecord(book, 'node');
console.log('bookEdge ', bookEdge)
booksUpdater(userProxy, bookEdge);
},
The problem i have is that comments always ends up on undefined as you can see above i've already set it. I also did this but i am still not getting an optimistic UI:
optimisticResponse: {
addBook: {
book: {
__typename: 'BookEdge',
cursor: uuidv1(),
node: {
id: uuidv1(),
title: bookTitle,
owner: username,
createdAt: Date.now(),
comments: {
__typename: 'CommentConnection',
edges: [],
pageInfo: {
endCursor: null,
hasNextPage: false
}
}
}
}
}
},
App don't crash with optimisticResponse code but no optimistic UI effect, but with the optimisticUpdater it's crashing with comments being undefined, for now I am settling with my updater:
updater: (store) => {
const userProxy = store.get(viewerId)
const payload = store.getRootField('addBook');
booksUpdater(userProxy, payload.getLinkedRecord('book'));
},
since the comments is undefined I guess we cannot use this for optimistic effect:
const comments = store.create(uuidv1(), 'comments')
comments.setLinkedRecords([], 'edges')
book.setLinkedRecord(comments, 'comments')
on my Book, this is the query which has the comments fragment that is undefined on optimistic update with the code above:
export default createRefetchContainer(
BookItem,
{
book: graphql`
fragment BookItem_book on Book
#argumentDefinitions(
count: { type: "Int", defaultValue: 5 }
cursor: { type: "String", defaultValue: null }
) {
id
title
owner
createdAt
...BookComments_book
}
`
},
graphql`
query BookItemQuery($id: ID!, $count: Int, $cursor: String) {
book: node(id: $id) {
...BookItem_book #arguments(count: $count, cursor: $cursor)
}
}
`
);
and now the query for the comments component where it gets the book.comments.edges is undefined:
export default createPaginationContainer(
BookComments,
{
book: graphql`
fragment BookComments_book on Book
#argumentDefinitions(
count: { type: "Int", defaultValue: 3 }
cursor: { type: "String", defaultValue: null }
) {
id
title
comments(first: $count, after: $cursor)
#connection(key: "BookComments_comments", filters: []) {
__typename
edges {
node {
id
text
owner
createdAt
}
}
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
}
}
`
},
{
direction: 'forward',
getConnectionFromProps: (props) => props.book && props.book.comments,
getFragmentVariables: (prevVars, totalCount) => ({
...prevVars,
count: totalCount
}),
getVariables: (props, { count, cursor }, _fragmentVariables) => ({
count,
cursor,
id: props.book.id
}),
query: graphql`
query BookCommentsQuery($id: ID!, $count: Int, $cursor: String) {
book: node(id: $id) {
...BookComments_book #arguments(count: $count, cursor: $cursor)
}
}
`
}
);
maybe this is an anti pattern? but i just wanted to have a optimistic effect for this
Some things are still not very clear to me about how those components and queries work, so I'll update this answer later. (I don't know if you want to return new book optimistically from node() query or add it to some list/connection of books)
Please check if I used correct type names (CommentConnection / CommentsConnection, etc)
optimisticUpdater: (store) => {
const userProxy = store.get(viewerId)
const owner = userProxy.getValue('username')
const commentsParams = { // must be same keys and values as in comments(first: $count, after: $cursor)
first: count,
after: cursor
}
// Create Book
const id = uuidv1();
const book = store.create(id, 'Book');
book.setValue(id, 'id');
book.setValue(bookTitle, 'title');
book.setValue(owner, 'owner');
book.setValue(Date.now(), 'createdAt');
// Create comments connection
const comments = store.create(uuidv1(), 'CommentConnection')
comments.setLinkedRecords([], 'edges')
// Create PageInfo
const pageInfo = store.create(uuidv1(), 'PageInfo')
pageInfo.setValue(null, 'endCursor')
pageInfo.setValue(false, 'hasNextPage')
pageInfo.setValue(false, 'hasPreviousPage')
pageInfo.setValue(null, 'startCursor')
// Link created records
comments.setLinkedRecord(pageInfo, 'pageInfo')
book.setLinkedRecord(comments, 'comments', commentsParams) // don't forget commentsParams with same values as are used in comments graphql query
// I'm not sure about this final part, because I don't really get how that app works, but if you want this book to show as optimistic response for `node(id: $id)`, you'll do something like this:
store.getRoot().setLinkedRecord(book, 'node', { id: id }) // same id as used in BookItemQuery
}
I am using jqgrid to display,sort and filter records. At the moment, I have go the js code working, but I think there is something wrong with my controller code, that is not populating the grid. I can see only an empty blak jqgrid with the message "No records to display". Please let me know whats going wrong.
Here is my code:
Controller:
public JsonResult GetData(string sidx, string sord, int page, int rows)
{
int pageIndex = Convert.ToInt32(page) - 1;
int pagesize = rows;
var custList = db.Customers.Select(
c => new
{
c.ID,
c.Company,
c.FirstName,
c.EMail,
c.Status
});
int totalCustomers = custList.Count();
var totalPages = (int)Math.Ceiling((float)totalCustomers / (float)rows);
if(sord.ToUpper() == "DESC")
{
custList = custList.OrderByDescending(s => s.FirstName);
custList = custList.Skip(pageIndex * pagesize).Take(pagesize);
}
else
{
custList = custList.OrderBy(s => s.FirstName);
custList = custList.Skip(pageIndex * pagesize).Take(pagesize);
}
var jsonData = new
{
total = totalPages,
page,
customers = totalCustomers,
rows = custList
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
Solved my problem. Dint know I would get the solution so quickly. I removed all the existing code from the controller and just added this:
public JsonResult GetData()
{
var customers = db.Customers.Select(m => new { ID = m.ID, Company = m.Company, FirstName = m.FirstName, Email = m.EMail, Status = m.Status }).ToList();
return Json(customers, JsonRequestBehavior.AllowGet);
}
This is all it needs,just two lines of code, rest of the functionalities, ie paging, sorting, filtering is already provided by jqwidgets:) Hope this helps someone who was facing a similar problem as mine.
The script is as follows:
var source =
{
//localdata: GetData(),
url: '/Client/GetData',
datatype: "json",
mtype: 'POST',
datafields: [
{ name: 'ID', type: 'int' },
{ name: 'Company' },
{ name: 'FirstName' },
{ name: 'EMail' },
{ name: 'Status' }
]
};
var dataAdapter = new $.jqx.dataAdapter(source);
// initialize jqxGrid
$("#jqxgrid").jqxGrid(
{
source: dataAdapter,
sortable: true,
filterable: true,
pageable: true,
columns: [
{ text: 'Client Id', datafield: 'ID', width: 200 },
{ text: 'Company', datafield: 'Company', width: 200 },
{ text: 'Username', datafield: 'FirstName', width: 180 },
{ text: 'Email', datafield: 'EMail', width: 100 },
{ text: 'Status', datafield: 'Status', width: 140 }
]
});
});