Skip to content

Input Binding

StefansArya edited this page Jan 7, 2021 · 4 revisions

Bind input with model

To enable two-way data binding with input element, you need to set sf-bind as element attribute that pointing your model property.

You may like to see the example first

Let's start by defining our model/component first

sf.model('example', function(My){
    // Any input on element will update this content and the binded view
    My.myInput = 0;
    My.myText = '';
    My.myRadio = 'radio2';
});
<!-- data on the model will be updated if input detected and vice versa -->
<input sf-bind="myText" type="text" />
<textarea sf-bind="myText" type="text"></textarea>

<input sf-bind="myRadio" type="radio" value="radio1" />
<input sf-bind="myRadio" type="radio" value="radio2" />

<input sf-bind="myFiles" type="file" />

When you need to obtain multiple value for checkbox or select, your property value should be an Array type. But if you like to check if the checkbox is checked or not, you need to set the model property as Boolean type. Using String data type will only return the last selected data.

<!-- You can also set property in `name` attribute -->
<select sf-bind="selectInput" typedata="number">
     <option value="1">Select 1</option>
     <option value="2">Select 2</option>
     <option value="3">Select 3</option>
</select>

<!-- Maybe using sf-each for the options? -->
<select sf-bind="selectInput" multiple>
     <option value="{{ x.val }}" sf-each="x in selectData">
        {{ x.text }}
     </option>
</select>

<!-- You can also set property in `name` attribute -->
<input sf-bind name="myCheckbox" type="checkbox" value="check1" />
<input sf-bind name="myCheckbox" type="checkbox" value="check2" />

To enable one-way data binding with input element, you need to define model property in sf-into attribute.

<!-- 'myInput' on the model will be updated if input detected -->
<!-- (View -> Model) -->
<input sf-into="myInput" type="text" typedata="number"/>

<!-- input will be updated if 'myInput' on the model was changed -->
<!-- (Model -> View)  -->
<input value="{{ myInput }}" type="text" />

<!-- You can also add prefixed value -->
<input value="It's {{ myInput }}" type="text" />

<!-- When binding to `img` attribute you need to use `:src` to avoid the browser process it first -->
<span :class="icon-{{myInput || 'nothing'}}" style="font-size: {{myInput}}" />

Event listener for binded property

This feature behaves like a proxy between the model property and the related elements.

Listen any changes

Useful if you want to process any changes, from the views or from the model.
Returned value will assigned as new value.

My.on$myInput = function(newValue, isM2V){
   // My.myInput still have the old value
   if(isM2V)
      console.log("Model value was changed, and going to modify related element");
   else
      console.log("Input value was changed, and going to insert to the model property");

  // return undefined; will not change the value
}

Listen changes (Model -> View)

This will triggered if any script is modifying myInput value on the model scope.
Returned value will only change related elements's value

My.m2v$myInput = function(newValue){
    // Format the currency only on the elements
    // But model value will always === newValue
    return formatCurrency(newValue);
}

Listen changes (View -> Model)

This will triggered on change/input event.
Returned value will be assigned as new value for other binded input/views and model's property value.

My.v2m$myInput = function(newValue){
    var oldValue = My.myInput;

    console.log("Value will be reverted in 3s to old value");
    setTimeout(function(){
        My.myInput = oldValue;
    }, 3000);
}