Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Viktor Fonic
    @vfonic
    Perhaps the default functionality could be to fire custom() regardless or together with check for optional/required?
    Viktor Fonic
    @vfonic
    I'm stuck with one issue (the previous one, I obviously solved after adding optional: true :) )
    I have a model that uses some logic to calculate the value of a property. A model is represented as a js class instance and the property is a getter on the class.
    This property is also in the schema and it shows correctly in the form (the value is filled). But, when I click the submit button, the field in the schema is empty and therefore the validation fails. What would be the best place to put this field's logic into so that the validation passes and the value gets submitted to the backend on submit?
    Here's a simple example:
    const CommunitySchema = new SimpleSchema({
      community: {
        type: String,
        label: 'Community',
      },
    });
    
    const CommunitySchemaBridge = new SimpleSchema2Bridge(CommunitySchema);
    
    class Record {
      get community() {
        return this._community || someSpecialMethodCalculatingTheCommunity();
      }
      set community(value) {
        this._community = community;
      }
    }
    
    const record = new Record();
    
    <AutoForm
      schema={CommunitySchemaBridge}
      model={record}
    />
    When I try to submit the form, I get "Community is required"
    Radosław Miernik
    @radekmie

    Hi @vfonic.

    About the first issue: it's not uniforms problem at all. It's how SimpleSchema works - we just use validator method to create a validator function - it's up to the schema if it calls custom or not. As I remember it checked the required-ness first, then the custom validation happened.

    About the second one: again, not uniforms problem. By default, SimpleSchema2Bridge calls the clean method (indirectly), which by default removes all unknown keys. In your case, it removes the _community, therefore validation fails. You have to either add it to the schema or disable cleaning.

    Viktor Fonic
    @vfonic
    Thanks @radekmie! I'll try adding _community to the schema. In the meantime, I made a workaround by not making community getter and setter, but a prop that holds the value (record.community = record.community || someSpecialMethodCalculatingTheCommunity();). Seems to have worked.
    Adam Tolley
    @refactorized
    In order to satisfy ESLint's demand that I not throw object literals that are not proper Error objects I needed to modify my jsonSchema bridge like so:
    function createValidator(schema) {
        const validator = ajv.compile(schema)
        return model => {
          validator(model)
          if (validator.errors && validator.errors.length) {
            let err = {
              ...new Error('Validation Error'), // best practice is to throw a real error
              ...{ details: validator.errors } // but we also need to add details for uniforms
            }
            throw err
          }
        }
      }
    as just throwing a details object in the constructor (as I think the docs used to read) doesn't work
    So question: should this even be using an throw catch mechanic, or could we possibly have it so that the validator function returns validation errors instead of throwing them (and returns nothing to signify success)?
    Again in consideration of best practices, an Error should signify that something broke in an unexpected, or unmitigated way; validation errors are nominal and an indication that the validator is doing it's job
    Adam Tolley
    @refactorized
    (obviously the catch mechanic would have to hang around in some manner to prevent breaking existing code)
    Radosław Miernik
    @radekmie

    It's not true that you are forced to throw an object literal - you have to throw anything with a certain property. Consider this code:

    throw Object.assign(new Error('Validation Error'), { details: validator.errors });

    It'll work correctly, as the thrown object has the details property, but also it's an Error instance. You can, of course, do it in three lines, creating the error first, then assign the property and finally throw it, or even create a custom ValidationError class.

    In general, I agree that we should have used returned value, it would simplify a few things. Especially typing - it is impossible to type check it without some higher abstraction like checked errors, effects, or continuations (none available in TypeScript at the moment).

    Then why is it implemented that way? Well, the first bridge ever was the SimpleSchema (the Meteor one), and its validator throws an error instead of returning it. It was perfectly fine, up to the point when we wanted to add onSubmitSuccess/onSubmitFailure and async validation. Of course, we managed to do so, but the solution is not very elegant.

    What I can suggest would be to use the above workaround for now. Also, please do file an issue (just quoting your messages is 100% cool) as I plan to start a v3 milestone to track all the planned and wished features. I'll also quote this message there.

    Adam Tolley
    @refactorized
    ok cool, will do - I get that I don't need to declare the variable first, the let was actually just left over from some other debugging code and our code is otherwise equivalent ( rest operator standing in for Object.assign)
    though using Object.assign has the advantage of quieting ESLint, not that it matters as either way is complying with the 'spirit' of that lint rule
    Radosław Miernik
    @radekmie
    It’s because the spreading works differently as the Object.assign, as the latter preserves the prototype.
    Adam Tolley
    @refactorized
    Ahh yeah, I see your point, I am bad at OO js and not ashamed of it. Interesting sidenote, using let to declare the variable first lets me throw anything I want because ESLint is not all that clever at the end of the day (but in my case I will just be disabling eslint for the line, as it most clearly matches my intent)
    I just filed the issue, thanks for your help
    Adam Tolley
    @refactorized
    Any Chance V3 will support a notion of dirty/pristine fields such that we can show validation errors for individual fields that have been visited, but not the whole form? Any chance V2 does this already and I am missing it?
    I think I can do this with custom fields and the validation api, such that on change, or on blur the field checks it's own value (right?), but I don't know that it's available from the standard components used by say the unifoms-material AutoForm component.
    Radosław Miernik
    @radekmie

    The thing with being pristine is that many fields are not focusable. If you meant an actual change, then yes, we do track it through the changedMap structure. A similar one may be used to track the pristine state.

    As I'm not planning to do so, I definitely would like to provide an example of how to implement it.

    Adam Tolley
    @refactorized
    I'm less concerned with pristine as I am with the ability to validate a single field as it changes (or on blur, or on change but with a throttling/delay )
    like onBlur would be nice, for fields that are focusable
    Adam Tolley
    @refactorized
    but really many of these concerns just come from my abuse of the autosave functionality, which submits (and validates) the form when I just want a good way to periodically pass the entire form state (valid or not) to logic which backs up the changes being made to the server
    put another way, is there a way to get at the state of an AutoForm in it's entirety without giving up the self management feature. I tried at first with to use ValidatedQuick form and propagate those changes to a model maintained in redux, but ran into a lot of performance issues
    Adam Tolley
    @refactorized
    (granted said perfomance issues may be entirely within my own code)
    Adam Tolley
    @refactorized
    oh good grief, I can just use onFormChange()
    Radosław Miernik
    @radekmie
    Actually we do use AutoForm rarely in our projects. Using onChangeModel is one possibility, but a simple wrapper to ValidatedQuickForm is the more common one. Another option is to use ref and call getModel on a form instance.
    I just saw that getModel is not documented... Well, maybe it's even better...? Anyway, you can use it.
    Adam Tolley
    @refactorized
    getModel is what I was looking for originally, I felt like it should exist, but couldn't find it. Is there any reason I should not use it?
    Radosław Miernik
    @radekmie
    The only against is that it's not documented.
    Adam Tolley
    @refactorized
    @radekmie Above when you say ' but a simple wrapper to ValidatedQuickForm' do you mean a class which extends it, or a component which wraps it. I am using a hooks component and wrapping a ValidatedQuickForm, managing the state inside my component and updating the model prop when changes are made. The problem I am having is that there is a lag between changes to this model prop and the change in the form.
    Console logs illustrate that each keystroke is in fact changing the state, and quickly, but the re-render seems to take place only after a brief delay and the changes are batched. This doesn't happen with a plain AutoForm which (reading the source) extends the ValidatedQuickForm and calls its setState method rather than passing through props. This difference is the only thing I can think of that might be causing input response lag. Does that sound plausible?
    If that's the case I have several workarounds (we discussed above) I can employ, but I would like to understand why I am seeing this behavior
    danyhiol
    @danyhiol
    Uncaught TypeError: tslib_1.__spreadArrays is not a function at SimpleSchema2Bridge.js.SimpleSchema2Bridge.getInitialValue Since the last update, I'm getting this strange error. I've found that it occurs for every array field define in simpleSchema2.
    Charles Eric Vincent
    @cvincent-atmanco
    Hey guys, just started looking over your library, it looks really promising!
    Just 1 quick question... I tried it out with a fairly simple JSON Schema, and I'm having trouble rendering array properties. It seems like it renders a field for it, but is not rendering the Add and Del buttons/icons, therefore I cannot add any data to the list field. Is this expected behaviour? Do I have to customize my form with ListFields under the AutoForm to make this work? I'm using uniforms-bootstrap4, but the problem is the same with uniforms-bootstrap3. My JSON schema looks like this:
    {
      "title": "Guest",
      "type": "object",
      "properties": {
        "competencies": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": { "type": "string" }
            }
          }
        }
      }
    }
    Charles Eric Vincent
    @cvincent-atmanco
    ^ Turns out it's because it requires the octicons icon package to be available in the app. Overriding the .octicon selector fixed it for me. Would be nice to implement other icons such as FontAwesome, or maybe a fallback such as a '+' or a '-' when octicons aren't available.
    Radosław Miernik
    @radekmie
    @refactorized Yes, it's actually true. The thing is that the change has to be fast enough to work properly. That's why AutoForm has both model and modelSync.
    @danyhiol It looks like we are depending on a too low version of tslib. Could you file this in an issue, please?
    Radosław Miernik
    @radekmie
    @cvincent-atmanco This theme was designed some time ago and it just stuck to the Octoicons. You can use the ListAddField (ListDelField) prop addIcon (removeIcon) to change it: https://github.com/vazco/uniforms/blob/d3f7f852c0b8d589b7415206d31448d4c54af990/packages/uniforms-bootstrap4/src/ListAddField.tsx#L24. It's really possible to detect any font icon in the component, so it won't work like that. We should definitely mention it in the docs though.
    danyhiol
    @danyhiol
    @radekmie done.
    Charles Eric Vincent
    @cvincent-atmanco
    @radekmie Thanks for the feedback.
    Also had another question. Does the JSON Schema Bridge supports the latest Draft Version 7? I'm specifically asking about the if, then & else keywords.
    Do you also know if there's issues with nested allOf keywords?
    Radosław Miernik
    @radekmie
    @cvincent-atmanco Partially. Currently we are not extracting much information from such keywords, but if you are using them just for the validation part, then it works.
    danyhiol
    @danyhiol
    I'm getting another weird error: Uncaught TypeError: Class constructor _a cannot be invoked without 'new'. This is after updating to the very last version.
    Radosław Miernik
    @radekmie
    @danyhiol I saw your comment and posted a few questions - will get to it later today
    danyhiol
    @danyhiol
    There is a strange behavior happening with arrays-field. image - image. When defining an array with minCount and options, there are null entries in the array. While simpleSchema requires using minCount to make an array not empty.
    Radosław Miernik
    @radekmie
    Yep, that's weird.
    I think it actually worked in the past...
    As always, file an issue please.
    And thanks again for a report.
    danyhiol
    @danyhiol
    @radekmie okay, that has been done.