Closed i-salameh95 closed 1 year ago
You should create a plugin that does it. Simply put - a muliti field plugin.
thanks, is there example on this? I have read the doc. but there is nothing about multi field plugin
Well, look. Each plugin returns a list of elements. Usually it's just one, but you can return two or more. It's quite trivial.
If you don't manage to set it up, let me know. I'll make one (useful to have anyway). If you do, please share it using a PR. :)
Do u mean that from get_form_field_instances that I should return 2 instances of the same field? I'm trying from yesterday to handle this, but with no luck. please could you help me on this ?
Check this plugin:
It only returns one field. You should return two and take care of the validation.
I have done this: but this doesn't return anything, it shows that successfully my plugin added to the form, but the form is empty...
def get_form_field_instances(
self, request=None, form_entry=None, form_element_entries=None, **kwargs
):
"""Get form field instances."""
widget_attrs = {
"class": theme.form_element_html_class,
"type": "email",
"placeholder": self.data.placeholder,
}
field_kwargs = {
"label": self.data.label,
"help_text": self.data.help_text,
"initial": self.data.initial,
"required": self.data.required,
"widget": TextInput(attrs=widget_attrs),
}
field2_kwargs = {
"label_confirm": self.data.label_confirm,
"help_text": self.data.help_text,
"initial": self.data.initial,
"required": self.data.required,
"widget": TextInput(attrs=widget_attrs),
}
if self.data.max_length:
try:
field_kwargs["max_length"] = int(self.data.max_length)
except ValueError:
field_kwargs["max_length"] = None
else:
field_kwargs["max_length"] = None
field_kwargs["min_length"] = None
return [(self.data.name, EmailField, field_kwargs), (self.data.name_confirm, EmailField, field2_kwargs)]
OK. I'll take a look.
FINALLY, I have successfully added the plugin that will make the email and confirmation email: here is the code of the plugin:
fobi_form_elements.py file
class MultiFieldPlugin(FormFieldPlugin):
"""SampleTextareaPlugin."""
uid = "confirm_another"
name = "Confirm Email"
form = MultiFieldForm
group = "Samples" # Group to which the plugin belongs to
def get_form_field_instances(
self, request=None, form_entry=None, form_element_entries=None, **kwargs
):
"""Get form field instances."""
widget_attrs = {
"class": theme.form_element_html_class,
"type": "email",
"placeholder": self.data.placeholder,
}
field_kwargs = {
"label": self.data.label,
"help_text": self.data.help_text,
"initial": self.data.initial,
"required": self.data.required,
"widget": TextInput(attrs=widget_attrs),
}
field2_kwargs = {
"label": self.data.label_confirm,
"help_text": self.data.help_text,
"initial": self.data.initial,
"required": self.data.required,
"widget": TextInput(attrs=widget_attrs),
}
if self.data.max_length:
try:
field_kwargs["max_length"] = int(self.data.max_length)
except ValueError:
field_kwargs["max_length"] = None
else:
field_kwargs["max_length"] = None
field_kwargs["min_length"] = None
return [(self.data.name, forms.EmailField, field_kwargs), (self.data.name_confirm, forms.EmailField, field2_kwargs)]
form_element_plugin_registry.register(MultiFieldPlugin)
forms.py file
class MultiFieldForm(forms.Form, BasePluginForm):
"""Form for ``MultiFieldForm``."""
plugin_data_fields = [
("label", ""),
("name", ""),
("label_confirm", ""),
("name_confirm", ""),
("help_text", ""),
("initial", ""),
("max_length", str(DEFAULT_MAX_LENGTH)),
("required", False),
("placeholder", ""),
]
label = forms.CharField(
label=_("Label"),
required=True,
widget=forms.widgets.TextInput(
attrs={"class": theme.form_element_html_class}
),
)
name = forms.CharField(
label=_("Name"),
required=True,
widget=forms.widgets.TextInput(
attrs={"class": theme.form_element_html_class}
),
)
label_confirm = forms.CharField(
label=_("Label of Confirmation email"),
required=True,
widget=forms.widgets.TextInput(
attrs={"class": theme.form_element_html_class}
),
)
name_confirm = forms.CharField(
label=_("Name of Confirmation email"),
required=True,
widget=forms.widgets.TextInput(
attrs={"class": theme.form_element_html_class}
),
)
help_text = forms.CharField(
label=_("Help text"),
required=False,
widget=forms.widgets.Textarea(
attrs={"class": theme.form_element_html_class}
),
)
initial = forms.EmailField(
label=_("Initial"),
required=False,
widget=forms.widgets.TextInput(
attrs={"class": theme.form_element_html_class}
),
)
max_length = forms.IntegerField(
label=_("Max length"),
required=True,
widget=NumberInput(
attrs={
"class": theme.form_element_html_class,
"min": str(DEFAULT_MIN_LENGTH),
}
),
initial=DEFAULT_MAX_LENGTH,
validators=[MinValueValidator(DEFAULT_MIN_LENGTH)],
)
required = forms.BooleanField(
label=_("Required"),
required=False,
widget=forms.widgets.CheckboxInput(
attrs={"class": theme.form_element_checkbox_html_class}
),
)
placeholder = forms.CharField(
label=_("Placeholder"),
required=False,
widget=forms.widgets.TextInput(
attrs={"class": theme.form_element_html_class}
),
)
def clean(self):
super(MultiFieldForm, self).clean()
max_length = self.cleaned_data.get("max_length", DEFAULT_MAX_LENGTH)
if self.cleaned_data["initial"]:
len_initial = len(self.cleaned_data["initial"])
if len_initial > max_length:
self.add_error(
"initial",
_(
"Ensure this value has at most {0} characters "
"(it has {1}).".format(max_length, len_initial)
),
)
email_name = self.cleaned_data["name"]
email_confirm_name = self.cleaned_data["name_confirm"]
print(email_confirm_name)
print(email_name)
if email_name == email_confirm_name:
self.add_error(
"name_confirm",
_(
"email and email confirm must have different names"
),
)
I think I must have also validate the data of the two fields on submit ( the data must match ) and according to doc. this is done in _submit_plugin_formdata , am I right ?
Hello, I'm struggling to find where I should add the validation code of the two email if they matched or not. should it be in submit_plugin_form_data , I have tried that, but the form is submitted successfully ! even the two emails are not the same.
def submit_plugin_form_data(self,
form_entry,
request,
form,
form_element_entries=None,
**kwargs):
email = form.cleaned_data.get(self.data.name, None)
email_confirm = form.cleaned_data.get(self.data.name_confirm, None)
if email and email_confirm and email != email_confirm:
form.add_error(self.data.name, ValidationError("Emails are not the same"))
return form
please if you could direct me, I will be so thankful..
You are in the right direction. I'll answer you today, later on, OK?
I started in dev branch: https://github.com/barseghyanartur/django-fobi/tree/dev/src/fobi/contrib/plugins/form_elements/fields/email_repeat
It's not yet working, but shows the intention.
Ok, thanks a lot for your intention, I will follow the branch updates.
What is important to know, is that the solution will be based on this form field and widget. Those parts take care of the validation.
I will pull the branch and use it, I really appreciate your time and help a lot.
btw: I'm trying to use django-fobi in Jobs project, every job ( Apply Form) has different form than the other, so the django-fobi suite my needs, but the admin needs some extra fields, like email match, and related fields ( like when the user press Yes from choices, so another text field should be filled)..
So I'm trying to test everything in this package.
So, it's finished in the dev
branch. Instructions are left in the README. Please, evaluate it for a couple of days. If all is well, I'll make a new release shortly.
is there something error on the dev branch?
I have add this to requirements.txt: django-fobi@git+https://github.com/barseghyanartur/django-fobi@dev
every time I try to pull the git branch, it gives me error:
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 69342: character maps to <undefined>
Sorry, this looks like a windows issue with docker. Alternatively, you could go for classic virtualenv/sqlite setup.
Ok. I have fix the issue by delete fobi- main branch from site-packages and replace it with one from dev branch. at all, the Email repeat works very well, but I think there should be 2 labels for each input when you insert the Email Repeat plugin. ( e.g: email, confirm email address) but what appear is one label for the two input. which is the label of Email repeat element. See the screenshot for what I mean:
It might depend on how are you going to use it. See the example below. I think it's just fine.
Ok, I have test it. I think its totally works well, you could please close this ticket.
OK. I'll make a release today.
Hello, How to create email and email confirmation field in django-fobi ? or in general two fields related to each other: 1st case: the two fields must be identical 2nd case: if field number 1 is filled with yes ( yes/no field) , so the user must be fill the field number 2 and vice versa ?