Skip to content
StefansArya edited this page May 12, 2020 · 5 revisions

Initialize/Define Model

sf.model('something', function(self, other){
    self.text = 'My Name';

    // Run something after this model was loaded on the DOM
    self.init = function(){
        // self.$el('.selector');
    }
});

Let's start with this simple element in the document body.
The mustache template will always synced with the model's self.text.

<sf-m name="something">
    <span>{{ text }}</span>
    Above will turn into below after the script is running.
<!-- <span>My Name</span> -->
</sf-m>

If you're confused, you can try the SharedModel, or Binding example and do some experiment.

Note:

  • Shared Model: All sf-m element with same name will use existing model and sync it's value on each sf-m element.
  • If you don't want to use shared model, the sf.component is your choice
  • The element with binded text shouldn't be replaced with another element because it will remove the binding feature.
  • The framework will not dive/parse into any custom element (element tag with-dashes), you should add sf-parse to the element attribute if you want it become part of current scope. Because the custom element can be an component too.
<sf-m>
   <div>
      <custom-element sf-parse>
          {{ parseMe }}
      </custom-element>
   </div>
</sf-m>

Element collection

After any element with <sf-m> tag was inserted into DOM, the model will have $el property that contains collection of <sf-m> elements. Component also have $el feature, but will always one element because it's not shared model.

<sf-m name="test">
    <div>{{ first }}</div> | <div>{{ second }}</div>
</sf-m>

<sf-m name="test">
    <div>{{ second }}</div> | <div>{{ first }}</div>
</sf-m>
sf.model('test', function(self){
    self.first = "first";
    self.second = "second";

    // This will be called everytime new sf-m element is created
    self.init = function(){
        // Count of sf-m element
        self.$el.length === 2;

        // Count of div element
        self.$el('div').length === 4;
    }
});

Enveloped template

Enveloped template can only be used for special mustache with @ symbol, like {{@exec ... }} or {{@if ... }}.
It's supposed to be used for defining safe HTML template inside an dynamic template.
The enveloped template would looks like {[ <div>HTML here, and also the {{ model.data }} too</div> ]}

Conditional template

Make sure you write in ES5 because browser doesn't use transpiler.

sf.model('...', function(self){
    self.view = undefined;

    self.do = {stuff:function(){/* called, but do nothing for now */}};
    self.finished = function(){
        console.log("You will see I will be called :)");
    }
});

Because view is undefined, below will run do.stuff, finished, and output enveloped template.

<div>
{{@if view === true :
    {[ <div>I'm not visible</div> ]}

  @elseif view === undefined:
    do.stuff();
    finished(true);
    {[ <b>I'm visible!!</b> ]}

  @else:
    {[ <div>I'm not visible</div> ]}
}}
</div>

Executable template

This feature can be a replacement of <script> tag, and can access your model properties directly. This feature also available for sf-repeat-list, and will be able to obtain key or value of the array.

For the example let's start with simple usage like:

  • Creating elements with for loop
  • Call alert
  • Create <br> element
  • And output HTML without escaping
sf.model('something', function(self, other){
    self.number = [1, 2, 3, 4, 5];
});
<sf-m name="something">
    <span>
    {{@exec
        for(var i = 0; i < 5; i++){
            {[ <label>i -> {{ i }}</label> ]}
        }

        myAlert("hello");
        {[ <br> ]}

        // Below will displaying the data without escaping the html
        // Always make sure you have secured the output
        // And maybe escaping HTML tags before returning
        @return '<b>' + number.join(',') + '</b>';
    }}
    </span>
</sf-m>

And the HTML output content will be escaped like below

<sf-m name="something">
    <span>
        <label>i -&gt; 0</label>
        <label>i -&gt; 1</label>
        <label>i -&gt; 2</label>
        <label>i -&gt; 3</label>
        <label>i -&gt; 4</label>
        <br>
        <b>1,2,3,4,5</b>
    </span>
</sf-m>
Clone this wiki locally