Search code examples
javascripttwitter-bootstrapknockout.jsbootstrapvalidator

knockout bootstrap validation callback?


I don't know where to start, but I will do my best to explain my problem.

I've been working with knockout for a while now, I think 5 years, and never had to do this or something similar.

Well, we have a big application and is almost finished, but we need to replace some parts of the application with KO components.

In one of these components it's really important to have a data-bv-callback-callback to validate the data entered in that field, the thing is that this, is not KO compliance, and i'm not finding a way to get this working, so i need a hand.

I've created a JS Fiddle, as an example (well, I took the example from the page of bootstrapvalidator).

<form id="callbackForm" class="form-horizontal" data-bv-feedbackicons-valid="glyphicon glyphicon-ok" data-bv-feedbackicons-invalid="glyphicon glyphicon-remove" data-bv-feedbackicons-validating="glyphicon glyphicon-refresh">
    <div class="form-group">
        <label class="col-lg-3 control-label" id="captchaOperation"></label>
        <div class="col-lg-2">
            <input type="text" class="form-control" name="captcha" data-bv-callback="true" data-bv-callback-message="Wrong answer" data-bv-callback-callback="checkCaptcha" />
        </div>
    </div>

    <div class="form-group">
        <label class="col-lg-3 control-label">Knockout</label>
        <div class="col-lg-2">
            <input type="text" class="form-control" data-bind="value: Value" name="knockout" data-bv-callback="true" data-bv-callback-message="Wrong answer" data-bv-callback-callback="checkCaptchaKO" />
        </div>
    </div>
</form>

https://jsfiddle.net/rothariger/9hmmc3e1/

Can someone point me in the right direction?

Thanks for any help. Regards.

ps: I know that in the example that I passed, I could put data-bv-callback-callback="myViewModel.checkCaptchaKO", but I couldn't do that, because I'm on a component, and I don't know what's my scope.


Solution

  • You can use ko.dataFor() (docs) to dynamically get the viewmodel associated with a certain element.

    The element that triggered the validation is passed as the third parameter to the callback.

    function randomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    };
    
    function checkCaptcha(value, validator, $field) {
        var vm = ko.dataFor($field[0]);
        return +value === vm.captcha1 + vm.captcha2;
    };
    
    $(function() {
        ko.applyBindings({
            captcha1: randomInt(1, 10),
            captcha2: randomInt(1, 20),
            Value: ko.observable()
        });
        $('#callbackForm').bootstrapValidator();
    });
    <link href="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.2/css/bootstrapValidator.min.css" rel="stylesheet"/>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.2/js/bootstrapValidator.min.js"></script>
    
    <form id="callbackForm" class="form-horizontal" data-bv-feedbackicons-valid="glyphicon glyphicon-ok" data-bv-feedbackicons-invalid="glyphicon glyphicon-remove" data-bv-feedbackicons-validating="glyphicon glyphicon-refresh">
    
        <div class="form-group">
            <label class="col-lg-3 control-label" id="captchaOperation">
                <span data-bind="text: captcha1"></span> +
                <span data-bind="text: captcha2"></span> =
            </label>
            <div class="col-lg-2">
                <input type="text" class="form-control" data-bind="textInput: Value" name="knockout" data-bv-callback="true" data-bv-callback-message="Wrong answer" data-bv-callback-callback="checkCaptcha" />
                <span data-bind="if: Value">You entered <span data-bind="text: Value"></span>.</span>
            </div>
        </div>
    
    </form>

    I recommend to look into knockout-validation, a knockout-aware validation framework makes more sense in this context.