Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MvvmFX validation with JFoenix controls #593

Open
piterso opened this issue Jun 18, 2019 · 2 comments
Open

MvvmFX validation with JFoenix controls #593

piterso opened this issue Jun 18, 2019 · 2 comments

Comments

@piterso
Copy link

piterso commented Jun 18, 2019

Is it possible to use JFoenix Validators with mvvmFX Validators way?

Using yours Wiki on how to use validation in MvvmFX https://github.com/sialcasa/mvvmFX/wiki/Validation

i create example app but I use controls from JFoenix library and in this library i got very cool way of defining validators.

For example i define TextField in my FXML view file:

<JFXTextField fx:id="username" promptText="%Name" labelFloat="true">
    <validators>
        <RequiredFieldValidator message="%NameRequiredError"/>
    </validators>
</JFXTextField>

Then i create field in Code Behind View
@FXML private JFXTextField username;

and to achieve validation and error message i have to write:

emulationName.focusedProperty().addListener(
    (ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
        if (!newValue) emulationName.validate();
    });

and when i do all this when field is empty i got message like this:

jfoenix_way

When i follow your article on how to do validation in mvvmFX I end up with this ControlsFX look:

controlsfx_way_way

I would like to have all the validation logic in ViewModel but also would like to stick with JFoenix TextField.
Do you have any ideas how i can achieve that?

@manuel-mauky
Copy link
Collaborator

I haven't used JFoenix so I don't know the details here. Based on your example code it looks like JFoenix is also mixing up validation logic and visualisation like the standard ControlsFX.
If you want to use it with mvvmfx-validation you would only use the visualisation part of JFoenix while implementing the validation logic the mvvmFX-way.

To do this you would need to implement your own ValidationVisualizer with JFoenix. As a reference you could use the ControlsFxVisualizer.
As I don't know the details of the JFoenix validation API I don't know how hard or easy this would be or if this is even possible.
If you have any questions I'm happy to support.

@No3x
Copy link

No3x commented Jul 19, 2019

I have looked into this just out of curiosity. I dynamically add a validator per control, if there is a error and set their error to true so they show up. This is the only way, because validation logic and visualisation are mixed up.
The approach is incompatible with the declaration of Validators (<validator>) in the View but I think that's okay because they do not belong there anyway.
Visualization of errors works with JFXComboBox, JFXDatePicker, JFXPasswordField, JFXTextArea, JFXTextField, JFXTimePicker only.

image

import com.jfoenix.controls.base.IFXValidatableControl;
import com.jfoenix.validation.RequiredFieldValidator;
import com.jfoenix.validation.base.ValidatorBase;
import de.saxsys.mvvmfx.utils.validation.Severity;
import de.saxsys.mvvmfx.utils.validation.ValidationMessage;
import de.saxsys.mvvmfx.utils.validation.visualization.ValidationVisualizerBase;
import javafx.scene.control.Control;
import org.kordamp.ikonli.javafx.FontIcon;

import java.util.Optional;

import static org.kordamp.ikonli.fontawesome.FontAwesome.EXCLAMATION_TRIANGLE;

/**
 * An implementation of {@link ValidationVisualizer} that uses the third-party library <a
 * href="https://github.com/jfoenixadmin/JFoenix">JFoenix</a> to visualize validation messages.
 * <p>
 * <strong>Please Note:</strong> The library JFoenix is not delivered with the mvvmFX library. If you like to use
 * this visualization you have to add the JFoenix library to your classpath, otherwise you will get
 * {@link NoClassDefFoundError}s and {@link ClassNotFoundException}s. If you are using a build management system like
 * <i>maven</i> or <i>gradle</i> you simply have to add the library as dependency.
 * This implementation is incompatible with validator declarations in the FXML.
 *
 */
public class JFoenixVisualizer extends ValidationVisualizerBase {

    private static final String ERROR = "error";
    private static final String REQUIRED_FIELD_MSG = "Required field";

    @Override
    public void applyRequiredVisualization(Control control, boolean required) {
        if (control instanceof IFXValidatableControl) {
            final IFXValidatableControl ifxValidatableControl = (IFXValidatableControl) control;
            decorateControl(ifxValidatableControl, Severity.ERROR, REQUIRED_FIELD_MSG, required);
        }
    }

    @Override
    public void applyVisualization(Control control, Optional<ValidationMessage> messageOptional, boolean required) {
        if (control instanceof IFXValidatableControl) {
            final IFXValidatableControl ifxValidatableControl = (IFXValidatableControl) control;
            ifxValidatableControl.resetValidation();

            if (messageOptional.isPresent()) {
                final ValidationMessage message = messageOptional.get();
                decorateControl(ifxValidatableControl, message.getSeverity(), message.getMessage(), required);
            } else if (required) {
                applyRequiredVisualization(control, required);
            }
        }
    }

    private void decorateControl(IFXValidatableControl control, Severity severity, String message, boolean required) {
        ValidatorBase validator;
        if (required) {
            validator = new RequiredFieldValidator();
        } else {
            validator = new ValidatorBase() {
                @Override
                protected void eval() {
                    hasErrors.set(true);
                }
            };
        }
       
        FontIcon warnIcon = new FontIcon(EXCLAMATION_TRIANGLE);
        warnIcon.getStyleClass().add(ERROR);
        validator.setSrcControl((Control) control);
        validator.setIcon(warnIcon);
        validator.setMessage(message);

        // Caution: setValidators is implemented as add by JFX..
        control.resetValidation();
        control.getValidators().setAll(validator);
        control.validate();
    }
}

Requires

compile 'de.saxsys:mvvmfx-validation:1.8.0-modified'
compile 'com.jfoenix:jfoenix:8.0.8'
compile 'org.kordamp.ikonli:ikonli-javafx:1.9.0'
compile 'org.kordamp.ikonli:ikonli-fontawesome-pack:1.9.0'

I had to set the visibility to protected to overwrite ValidationVisualizerBase methods.
It's messy and hacked - would not include into mvvmfx.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants