mbest / knockout.punches

A collection of enhanced binding syntaxes using Knockout 3+
http://mbest.github.io/knockout.punches/
238 stars 19 forks source link

Feature request: two way filters #67

Open cosmoKenney opened 7 years ago

cosmoKenney commented 7 years ago

Looks like this library isn't getting much updates, but I think it would be cool to have two way filters. I.e. a phone filter would take a 10 digit value like "1234567890" and convert it to "(123) 456-7890" as the value is being sent to the view. And then strips the formatting upon return the view-model.

I could see enabling this by adding an object the ko.filters object:

ko.filters.phone {
    read: function ( phoneOut ) { return phoneOut ? phoneOut.replace( /(\d{3})(\d{3})(\d{4})/, "($1) $2-$3" ) : ''; }
    write: function ( phoneIn ) { return (phoneIn || '').replace( /[^\d]/g, '' ); }
};

Could this somehow be wrapped in an computed prior to binding?

Update: copy and paste fixed.

Update again: And this would, obviously, be used like this:

<input value="{{CellPhone | phone}}" />
mbest commented 7 years ago

That's an interesting idea, but it could be done today by returning a computed.

ko.filters.phone = function (value) {
    return ko.pureComputed({
        read: function () {
            return (ko.unwrap(value) || '').replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");
        },
        write: function (phoneIn) {
            value((phoneIn || '').replace(/[^\d]/g, '');
        }
    });
};
cosmoKenney commented 7 years ago

Oh, perfect. For some reason I was thinking a filter could only return text. The computed solution is way cool.

mbest commented 7 years ago

I didn't actually test it, so let me know if you run into any problems. This actually isn't best practice in terms of performance because the computed will be re-created each time the value changes, but I'm not sure if there's another way to do it.