I'm using Ionic 4 with React and typescript.
I'm looking to create an alert with a email input and 2 buttons, "cancel" and "accept".
I want the "accept" button to only be available when the user is giving a valid email address. Therefore I want to use a regex in the input field handler, but the handler is never called, not when typing nor when pressing enter. How can I get it to get callled when the user is typing
async showAlert() {
var promise = await alertController.create({
header: "Recevez la photo dans votre boƮte mail",
inputs: [{
name: "email",
type: "email",
placeholder: "email",
handler: () => {
console.log("input Fild Hanlder Called");
}
}],
buttons: [{
text: "cancel",
role: "cancel",
handler: cancel => {
console.log("cancel");
}
},
{
text: "envoyer photo",
role: "send",
handler: (alertData) => {
console.log((/^[a-zA-Z0-9]+#[a-zA-Z0-9]+\.[A-Za-z]+$/.test((alertData.email))));
}
}
]
});
await promise.present();
let result = await promise.onDidDismiss();
}
tl;tr This feature is not implemented in ionic4: ionic/issues/19059
After comparing the ionic code for rendering a checkbox in an alert and any other input element I came to the sad conclusion that the feature you are looking for doesn't exist.
At the moment it looks like handler on input in alerts is only supported for checkboxes and radio-inputs
There was a PR for ionic3 that added the validators option to AlertInputs to provide angular form validation but its not there anymore in ionic4.
There is still an open issue for ionic3 requesting input validation for alert inputs but non for ionic4 as far as I can see.
Update: new feature request for ionic4
Related
I've created a custom dialog with a dropzone in order to upload files and images to our server. By default the dropzone renders with 'Drop an image here' / 'Browse for an image'.
As part of the tinymce editor options file_picker_type allows setting of the default dropzone and I wondered how to access these options for a stand-alone dropzone?
My tinymce options include:
tinymce.init({
file_picker_types: 'file image'
});
My upload dialog config looks something like this:
const upload_config = {
title: 'Upload files',
size: 'medium',
body: {
type: 'panel',
{
type: 'dropzone',
name: 'file_drop',
types: 'file image' //// <----- something like this???
}
]
},
buttons: [
{
type: 'cancel',
name: 'closeButton',
text: 'Cancel',
},
{
type: 'submit',
name: 'submitButton',
text: 'Upload',
buttonType: 'primary'
}
],
onSubmit: (api) => {
// handle upload here
}
};
Anybody managed to fathom this? The tinymce docs are in no way comprehensive as they simply say "A dropzone is a composite component that catches drag and drops items or lets the user browse that can send a list of files for processing and receive the result." but give no details on how to actually do that with a stand alone dropzone.
I've managed to make it all work, but this is the last hurdle.
Thanks in advance
Are you trying to override the default image/file upload dialog with the custom one? I'm asking because I see the file_picker_types config option. To do so, you will need to use the file_picker_callback.
If it's something else and you are not trying to override the default dialog, use this interactive example as a base. You will need to:
a) Register the custom button with a setup function:
setup: function (editor) {
editor.ui.registry.addButton('custom-upload', {
icon: 'upload',
onAction: function () {
editor.windowManager.open(upload_config)
}
})
},
b) Add this button to the toolbar via toolbar: 'custom-upload'. This way, pressing the button will open the dialog based on the upload_config variable.
c) You've made a mistake in the panel config. I guess, you forgot to create the items array at the beginning. Instead of
type: 'panel',
{
type: 'dropzone',
name: 'file_drop',
types: 'file image' //// <----- something like this???
}
]
There should be:
type: 'panel',
items: [
{
type: 'dropzone',
name: 'file_drop',
label: 'Dropzone',
}
]
I've created this fiddle as a quick demo: https://fiddle.tiny.cloud/3iiaab
P.S. The dropzone component does not support file types. But you can check the file types after they are uploaded.
I need to test if a button is conditionally enabled after text inputs are filled out.
Right now simply checking to see if they are disabled works with the following:
expect(screen.getByTestId('select-service-btn').closest('button')).toBeDisabled();
But I want to check if they get enabled after input values are filled out.
This is what I currently have.
it('Should test to see if a button gets enabled when forms are filled out', () => {
const firstInput = screen.getByTestId('firstName-input');
const lastInput = screen.getByTestId('lastName-input');
const emailInput = screen.getByTestId('email-input');
expect(screen.getByTestId('select-service-btn').closest('button')).toBeDisabled();
fireEvent.change(firstInput, {
target: { value: 'test content' },
});
fireEvent.change(lastInput, {
target: { value: 'test content' },
});
fireEvent.change(emailInput, {
target: { value: 'test content' },
});
expect(screen.getByTestId('select-service-btn').closest('button')).not.toBeDisabled();
})
I want to say this would check to see if a button is disabled, mimic filling out the necessary inputs, and then check to see if the button changed from disabled to enabled. But the test fails.
I'd like to use notifications to push form feedback, instead of the inline messaging. e.g.
<Form.Item label="Name">
{getFieldDecorator("name", {
rules: [
{
validator(rule, value, callback) {
if (!value) {
callback("Enter Your Name");
// I'd like to use this instead:
// notification.open({
// message: "Enter Your Name",
// description:
// 'This is the content of the notification.',
// })
}
callback();
}
}
]
})(<Name />)}
</Form.Item>;
Is is possible to validate form fields and maintain the visual feedback (i.e. things like the border-color change), without the inline messaging?
You can do as you showed in your code and use css to hide error messages.
display: none
You can throw custom error message using this.props.form.setFields
this.props.form.setFields({
user: {
value: values.user,
errors: [new Error('forbid ha')],
},
});
Reference for form.setFields
The following screenshot shows a combined form for sign-in and sign-up:
The following module is used to render the AuthView:
MyApp.module("User", function(User, App, Backbone, Marionette, $, _) {
User.AuthView = Marionette.ItemView.extend({
className: "reveal-modal",
template: "user/auth",
ui: {
signInForm: "#signin-form",
signUpForm: "#signup-form"
},
events: {
"focus input": "onFocus"
},
onFocus: function() {
console.log("Some input field has received focus.");
},
onRender: function() {
this.signInForm = new Backbone.Form({
schema: {
signInEmail: {
type: "Text",
title: "E-Mail address"
},
signInPassword: {
type: "Password",
title: "Password"
}
}
}).render();
this.ui.signInForm.prepend(this.signInForm.el);
this.signUpForm = new Backbone.Form({
schema: {
signUpEmail: {
type: "Text",
title: "E-Mail address"
},
signUpPassword: {
type: "Password",
title: "Password"
},
signUpPasswordConfirmation: {
type: "Password",
title: "Password confirmation"
}
}
}).render();
this.ui.signUpForm.prepend(this.signUpForm.el);
}
});
});
How can I automatically focus the first field in each sub-form whenever it is rendered? The first fields would be signInEmail for the signInForm and signUpEmail for the signUpForm.
I tried to listen to focus input events. Such an event is triggered when I click into one of the input fields, not before.
Meanwhile, inspired by the current answers I came up with the following helper function:
focusFirstFormField: function(form) {
if (_.isUndefined(form)) {
throw "IllegalStateException: Form is undefined."
}
// TODO: AuthView does not focus first sign-in field.
var firstInput = form.find(':input:first');
if (_.isObject(firstInput)) {
if (firstInput.length > 0) {
firstInput = firstInput[0];
}
else {
throw "IllegalStateException: Form find returns an empty jQuery object."
}
}
_.defer(function() {
firstInput.focus();
});
}
There is still need for improvement, though.
The events object are DOM events which are generally triggered by the user so that's not what you'll likely want to use in this case.
If I'm understanding you correctly you would like to put the focus in the first input of each of the forms but since you can only have focus on one thing at a time and they are rendering together you'll have to choose one or the other.
The simplest option is to add another line at the end of onRender focusing on the input. If your input is generating an input something like this:
<input type="text" name="signInEmail">
Then you can add:
this.$('[name=signInEmail]').focus();
If not you'll have to change the selector this.$(xxxx).focus() to suit.
You can use onDomRefresh event of the view. It will be triggered after view rendered and Dom refreshed.
onDomRefresh: function() {
this.focusFirstInput();
};
focusFirstInput: function() {
this.$(':input:visible:enabled:first').focus();
};
This solution applies to general cases. However, pay attention if you are using Bootstrap. I can't get this work there. Instead, I set autofocus: 'autofocus' in the field and it works.
You can add it to onRender method.
this.ui.signInForm.find('input[type=text]:first').focus();
this.ui.signUpForm.find('input[type=text]:first').focus();
On the onRender method I do :
$(this.el).find(':input[autofocus]').focus();
And I add the autofocus="" flag onto my HTML node. This works for refresh.
I am using Ext.direct.RemotingProvider . At the server side I make some validation checks. The Respond is send back in JSON format.
If i find any errors when making validation checks, the field success = false, and errors will contain the error.
I am trying to figure out, how do i reflect errors i found in the server side in the form (client side).
In the link below there is an example of what i want to achieve. When the client press on "submit" an error message will occur in the form, how does it work ?
Example
In the code i post in the bottom the following happens:
in the browser there are 2 fields (Name,Email) and 2 buttons.
the fields are irrelevant for now. they are used as dummies.
Each time the user press on "Add" button, a new action is added into callBuffer of Ext.direct.RemotingProvider
When the user press on "Apply" button, all the actions are being sent to the router (MVC model) and from there to a specific controller. (the function sfw.Direct.getProvider('sfwProvider').combineAndSend() is triggered).
As for now, i intentionally fails the respond and create an error field, just like the example link i added in the beginning of the Thread.
i put in the errors field {email="Already exists"}.
but i see not effect in the form..
what am i doing wrong ?
Code:
appWiki.main_panel = new Ext.FormPanel({
renderTo: 'extjs_panels_container'
, id: 'appWiki_main_panel'
, name: 'appWiki_main_panel'
, defaultType: 'textfield'
, items: [
{
fieldLabel: 'Name',
name: 'name'
}
,{
fieldLabel: 'Email',
msgTarget: 'side',
name: 'email'
}]
,buttons:[
{xtype: 'sfw.Button'
, text: 'Add'
, handler: function(){sfw.rule.store.api.readByRowId({data: {_ROWID_: 1}});}
}
,{text: 'Submit'
, handler: function(){
appWiki.main_panel.getForm().submit({
});
}
}]
,api: {
// The server-side must mark the submit handler as a 'formHandler'
submit: sumbitAllRequests
}
, load: function()
{
setTimeout("hide_loading_mask()",2000);
}
});
In the JSON response you need the following structure
{ "result" : { "success": false, "errors": { "name of field" : "validation message" } }
Where "name of field" is the name config option in your field, and "validation message" is the message you want to display to the user.
When you send a response like that ExtJS will take care of the rest.
EDIT: You may also need to enable QuickTips:
Ext.QuickTips.init();
Add that line before you declare your form
EDIT 2: Also, make sure you're using the submit() method found on the BasicForm:
buttons:[{
text: 'Submit',
handler: function(){
basicInfo.getForm().submit({
params: {
foo: 'bar',
uid: 34
}
});
}
}],