Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ractive examples #3230

Open
dagnelies opened this issue Apr 24, 2018 · 28 comments
Open

Ractive examples #3230

dagnelies opened this issue Apr 24, 2018 · 28 comments

Comments

@dagnelies
Copy link
Contributor

In order to keep Ractive rocking, I think providing examples is a good way to go forward:

https://dagnelies.github.io/ractive-examples/

Contributions welcome, make it even greater. Possibly even linking it in the main site. Sorry if the style is not up to date. Most of it was done pre-theme-change.

@evs-chris
Copy link
Contributor

Nice!

@dagnelies
Copy link
Contributor Author

You can also suggest the next example you want ;)

@dagnelies
Copy link
Contributor Author

Hey @fskreuz, can you perhaps add the tag "help wanted"? Perhaps it'll attract some contribution. Thanks

@boussou
Copy link

boussou commented May 6, 2018

bravo

@dagnelies
Copy link
Contributor Author

dagnelies commented May 16, 2018

One more big demo: datatables!

https://dagnelies.github.io/ractive-examples/datatables/datatable.html

@boussou
Copy link

boussou commented May 16, 2018

nice ;-)

@shakeelosmani
Copy link

This is awesome and thanks for this. I want to see an example doing it the Ractive way where there are two sets of drop-down. One is list of US states and the other one is list of counties. Data for both are available as JavaScript array of objects. Also the requirement is to use select2 library to turn them into better select dropsdowns.

Well this is how I have done it, I wrote a decorator that on it's constructor calls select2 on the nodes.

But to dynamically change the options of county dropsdown I look for select on change and then build an Array depending on the state selected and rebuild a new array finally passing it to ractive set. This sounds and feels clunky because the problem was select2 changes the behavior of drop down and Ractive on- change doesn't fire when drop down value is changed. I am sure I am not adapting it correctly.

@dagnelies
Copy link
Contributor Author

@shakeelosmani Sure, sounds simple enough. Can you please provide the data and the way you currently do it now?

@shakeelosmani
Copy link

@dagnelies sure here you go.
counties.zip

link to select2 library:
https://select2.org/

The states have the keys in id property that is the key for counties for that state.

Thanks
Shakeel

@shakeelosmani
Copy link

@dagnelies

my implementation of functionally works correctly and here is a step by step images:

image

image

When the state of Hawaii is selected then counties shown are only for Hawaii

image

similarly when state of Alaska is selected the counties of Alaska are shown.

The code I have is as follows:

`

<div id="container"></div>

<script id="template" type="text/ractive">
  <select as-select2 id="tState" value="{{statesId}}">
    <option value="" disabled selected>Select a state</option>
    {{# states }}
      <option value="{{ id }}">{{ name }}</option>
    {{/ states }}
  </select>
  <br>
  <br>
  <select as-select2 id="tCounty" value="{{countyId}}">
    <option value="" disabled selected>Select a county</option>
    {{# counties }}
      <option value="{{ id }}">{{ name }}</option>
    {{/ counties }}
  </select>
</script>

<script src="/js/counties.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ractive"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.min.js"></script>
<script>

  function matchStart(params, data) {
    params.term = params.term || '';
    if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
      return data;
    }
    return false;
  }

  Ractive.decorators.select2 = function(node) {
    $(node).select2({
      matcher: function (params, data) {
        return matchStart(params, data);
      },
      width:'15%'
    });
    return {
      teardown () {
      },
      update () {
      }
    }
  }
  var ractive = new Ractive({
    el: $('#container'),
    template: $('#template').html(),
    data: {
      'counties':'',
      'states':states
    }
  });

  $('#tState').on('change', function (e) {
    var selectedState = $("#tState").val();
    var returnArray = [];
    ractive.set('counties','');
    ractive.set('statesId',selectedState);
    if(selectedState !== undefined)
    {
      countiesArray = propertyStateCounties[selectedState];
      for(var i = 0; i < countiesArray.length; i++){
        returnArray.push({'id':countiesArray[i], 'name':countiesArray[i]});
      }
      ractive.set('counties',returnArray);
    }
    else
    {
      ractive.set('counties','');
    }
  });

  $('#tCounty').on('select2:select', function (e) {
    var selectedCounty = $('#tCounty').val();
    ractive.set('countyId', selectedCounty);
  });
</script>
`

@dagnelies
Copy link
Contributor Author

dagnelies commented Jun 14, 2018

Well, I added the basic "dependent selects" example which is fairly straightforward. The one without "select2" plugin is here:

https://dagnelies.github.io/ractive-examples/forms/dependent_selects.html

The issue you face is because of the "select2" plugin. Making that one data-bound is a bit more work, and specific to that library. A re-usable component widget would be the way to go IMHO, like in the color picker example. However, doing so properly with that library looks like some work.

...as a side comment, even basic selects respond to keyboard navigation.

@shakeelosmani
Copy link

Thank you. Looks good I guess I need to brush up on mustache. I will go without select2 I guess.

@ceremcem
Copy link

ceremcem commented Jun 14, 2018

Late for the dropdown party, but I have a word or two on this topic. According to my experiments, a dropdown is the most complex component to build as it has lots of edge cases. Here is my dropdown component that might provide you another perspective (Note: Pug and Livescript can be compiled to HTML and Javascript respectively).

I would also suggest you use your own simple dropdown with sifter.js for search functionality. I can not provide a standalone dropdown component (it depends on ScadaJS at the moment) but here is my example implementation:

.ui.segment 
    ack-button(on-click="getCountries") Get Countries 
    
    dropdown(
        data="{{countries}}"
        selected-key="{{selectedCountry}}"
        async on-select="countrySelected")
        
    dropdown(
        loading="{{loadingCities}}"
        data="{{cities}}"
        selected-key="{{selectedCity}}")
        
    .ui.basic.message.
        Selected country: #[.ui.input: input(value="{{selectedCountry}}")] 
        and selected city: #[.ui.orange.label {{selectedCity}}]
require! 'superagent': request
require! 'superagent-jsonp': jsonp
...
require! 'superagent': request
require! 'superagent-jsonp': jsonp

# below are Ractive Handlers
export cities =
    'getCountries': (ctx) ->
        btn = ctx.component
        btn.state \doing
        err, res <~ request
            .get 'http://battuta.medunes.net/api/country/all/'
            .use jsonp {timeout: 100000}
            .query {key: 'd94e2d7fe5166543c6b7fd625347d5ba'}
            .end
        if err => return btn.error "Something went wrong while getting countries: ", err
        @set \countries, [{id: ..code, name: ..name} for res.body]
        btn.state \done...

    'countrySelected': (ctx, item, progress) ->
        console.log "Selected country is: #{item.id}"
        @set \cities, []
        @set \selectedCity, ''
        @set \loadingCities, yes
        progress!
        err, res <~ request
            .get "http://battuta.medunes.net/api/region/#{item.id}/all/"
            .use jsonp {timeout: 100000}
            .query {key: 'd94e2d7fe5166543c6b7fd625347d5ba'}
            .end
        if err
            return console.error "Something went wrong: ", err
        console.log "cities are: ", res.body
        @set \cities, [{id: ..region, name: ..region} for res.body]

...and here is the result:

dropdown-country-city

@shakeelosmani
Copy link

I finally did it this way, seems to work well.

https://github.com/shakeelosmani/ractive-select2-component

@shakeelosmani
Copy link

Hello, I want to do this where I have dependent fields that are databound and they update values dependent on change of certain inputs. I have a fiddle here : https://jsfiddle.net/pqts780m/

On the script side the goal of the code is written in the comments section. Any help or guidance is truly appreciated.

Thanks

@evs-chris
Copy link
Contributor

@shakeelosmani you were close, but you can't have computed values update other computed values that depend on computed values because there's no definitive stored value to start with as a base. If you make the down payment amount a plain value, then setting the percent can update it and changing the amount will cause the percent to invalidate and update any of its deps. Here's an updated fiddle. Interdependent computeds can get pretty tricky, which is why I typically add a calculate function to the instance, turn off two way binding on the inputs, and trigger the calculate method in on-change.

@shakeelosmani
Copy link

@evs-chris Yes you were right we are better off with the event driven model. I had managed to get it working. This is the fiddle: https://jsfiddle.net/rana_tigrina2002/15c4fs7d/

Thanks for all your help, it's cool to know that other way also which you managed on the updated fiddle.

@dagnelies
Copy link
Contributor Author

dagnelies commented Jul 2, 2018

Hi, I was on vacation, so it took me a while :)

I think the whole example/challenge boils down to two input values A and B related by a formula.
They depend on each other because changing either updates the other, while avoiding recursive loops.
Here is the approach I would choose:
https://jsfiddle.net/pqts780m/20/

I think the event based ones has the shortcoming that it doesn't react to model manipulation, while the other one with the computeds is rather contrived. The key to the simpler example are "shadow variables". The "getter" simply returns the tied variable, while the "setter" updates the related shadow variables.

@shakeelosmani
Copy link

@dagnelies that is cool and I must agree to the point raised about making it event driven means you lose out on change made to models, although in this particular case it wont cause a problem but I can see how that would affect in other situations. Thank you!

@dagnelies
Copy link
Contributor Author

@tmilker
Copy link

tmilker commented May 15, 2019

Anyone have an example of an async combobox(start typing, queries a url with what has been typed and populates a list below a text input to choose from)? Preferably in plain old javascript/ractive?

@evs-chris
Copy link
Contributor

@tmilker this uses a slightly convoluted macro to do it, but if it works for you, it's an already consumable plugin available here (or UMD or plain ractive component).

The gist of it is, bind the on-input event of the input element to call a function that replaces a promise for a list in the data. Then use {{#await list then items}}{{#each items}}...{{/each}}{{/await}} to display the list when the promise resolves.

@tmilker
Copy link

tmilker commented May 16, 2019

@evs-chris Thanks. I think I may just have to use your description of how it works and write my own. I don't want to add pre-processing dependencies to a legacy application which I think your solution requires. If I'm just not seeing the .min.js I can just include with a <script> tag, please let me know.

@evs-chris
Copy link
Contributor

There is a umd here, which should be a drop in for a script tag. It does require a fairly recent version of ractive, though, so it may not work depending on how legacy the app is.

@tmilker
Copy link

tmilker commented May 16, 2019

@evs-chris Well, thankfully using ractive is new in this project so I went from 1.3.4 to 1.3.6 but still having issues. Sorry to be a nuisance about this but do you have a Playground example that uses the UMD because I can't get it to work when I include the script and try to use the component in my template. I've checked Ractive.components and it doesn't appear to register itself so I tried registering it myself but I get:

Autocomplete.min.js:1 Uncaught (in promise) TypeError: Cannot set property 'RMAutocomplete' of undefined

@evs-chris
Copy link
Contributor

As long as it gets loaded after ractive, it should work. I believe in the global case, it automatically registers as Ractive.partials.RMAutocomplete, but you can install it normally using Ractive.use(RMAutocomplete.plugin()).

@anant-svc
Copy link

@dagnelies This issue page must be pinned to the repository and change title to "You must check all the Ractive Example before creating a new issue"

Why?

Because all examples are real world business logics that most web applications are using.

What you think?

@dagnelies
Copy link
Contributor Author

I think it could even be embedded into the main site ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants