Giter Club home page Giter Club logo

Comments (7)

miguelcobain avatar miguelcobain commented on August 19, 2024 1

Even Ember.Select has this issue: emberjs/ember.js#9369.
I think it would be a huge plus to support this. I also need this myself.

As a quick fix, you could try this:

//templates/task.hbs
{{ember-select 
  projects=projects 
  selected=model.project.content 
  select-item="projectSelected" 
  optionLabelPath="name"
}}

Binding to .content property usually works. What I don't like here is that the fact that the property is a promise is leaking to the templates. So see this as a workaround, not a proper definite fix.

from ember-cli-selectize.

sandreas avatar sandreas commented on August 19, 2024

Well, as a basic approach, you could implement optionComparePath and ensurePromise like shown below (this approach worked for me on non-multiple-selects binding the value, not the selection).

Explanation:
optionComparePath is needed, because ember-data-models are not beeing equal when using filter, although they have the same id (wtf?;). So i extended ember-cli-selectize with optionComparePath to ensure that they are seen as equal, even if they technically arent.

Multiple calls of "_valueDidChange" are avoided using "ensurePromise". Sorry for not having the time to create a nice and clean pull request with unit tests ;)

// reopen ember-cli-selectize in app.js (bad style, i know)
import EmberSelectizeComponent from 'ember-cli-selectize/components/ember-selectize';
import computed from 'ember-new-computed';
var get = Ember.get;

EmberSelectizeComponent.reopen({
    optionComparePath: 'content',
    _comparePath: computed('optionComparePath', function () {
        return this.get('optionComparePath').replace(/^content\.?/, '');
    }),
    _ensurePromise: function (content) {
        return new Ember.RSVP.Promise(function (resolve) {
            resolve(content);
        });
    },
    _valueDidChange: Ember.observer('value', function () {
        var content = this._ensurePromise(this.get('content'));
        var _this = this;
        content.then(function (resolvedObject) {
            var value = _this.get('value');
            var valuePath = _this.get('_valuePath');
            var comparePath = _this.get('_comparePath');
            var selectedValue = (valuePath ? _this.get('selection.' + valuePath) : _this.get('selection'));
            var selection;

            if (value !== selectedValue) {
                selection = resolvedObject ? resolvedObject.find(function (obj) {
                    if (comparePath === '') {
                        return value === (valuePath ? get(obj, valuePath) : obj);
                    }
                    return get(value, comparePath) === get(obj, comparePath);
                }) : null;
                _this.set('selection', selection);
            }
        });
    })
});

The Controller:

// articles.js, controller
import Ember from 'ember';

export default Ember.Controller.extend({
    parentArticles: function () {
        var _this = this;

        return this.store.filter('article', {parent: null}, function (article) {
            // unpersisted not allowed
            if (article.get('isNew')) {
                return false;
            }

            // articles with a parent not allowed
            if (article.get('parent.id')) {
                return false;
            }

            // self as parent not allowed
            if (article.get('id') === _this.get('model.id')) {
                return false;
            }

            return true;
        });

    }.property('model')
});

The Template:

        {{ember-selectize
        content=parentArticles
        optionValuePath="content"
        optionLabelPath="content.title"
        optionComparePath="content.id"
        value=model.parent}}

The Model:

import DS from 'ember-data';

export default DS.Model.extend({
    title: DS.attr('string'),
    children: DS.hasMany('article', {inverse: 'parent', async: true}),
    parent: DS.belongsTo('article', {inverse: 'children', async: true})
});

from ember-cli-selectize.

miguelcobain avatar miguelcobain commented on August 19, 2024

The general strategy would be to don't do anything until the promise resolves. If it isn't a promise, we just wrap it in a promise that always resolves and then we deal only with promises. Thanks for the code.

Minor thing, this:

return new Ember.RSVP.Promise(function (resolve) {
  resolve(content);
});

could be replaced with:

return Ember.RSVP.Promise.resolve(content);

i.e, a promise that resolves immediately.

from ember-cli-selectize.

sandreas avatar sandreas commented on August 19, 2024

Thank you. Wow that was a quick feedback ;) Yes, Promises are the key i think...

I'd love to see the optionComparePath as a feature in one of the next releases (just as a possibility to override the default compare-behaviour).

If i should create an extra issue for that, just give me a hint.

from ember-cli-selectize.

miguelcobain avatar miguelcobain commented on August 19, 2024

On a second thought, I think you may be doing something unecessary.

Currently ember-selectize uses optionValuePath to test equality.
Also, it uses selection to hold the selected object and value to hold its value according to value path.

I think your template should be:

{{ember-selectize
        content=parentArticles
        optionValuePath="content.id"
        optionLabelPath="content.title"
        selection=model.parent}}

Maybe the documentation should be more explicit on the selection vs value subject.
This is a different subject from the topic of this issue.

from ember-cli-selectize.

sandreas avatar sandreas commented on August 19, 2024

Well, it would take a bit more time to explain the whole thing. In short:

  • I wrap ember-selectize into my own component
  • I directly link the value to a belongsTo-Property on the model
  • If optionValuePath would be "content.id" like you described, changing the selected option results in an ember-data error, because the property "article.parent" cannot be an integer but must be a valid model
    So this is the only option:
{{ember-selectize
        content=parentArticles
        optionValuePath="content"
        optionLabelPath="content.title"
        selection=model.parent}}

But: If i compare the model article.parent (which is a relationship) with the model, store.find('article') delivers after fullfilling its promise, these two are not equal (neither with Ember.isEqual nor with ===). I did not find out why yet.

So my only option was to extend ember-cli-selectize with optionComparePath, which is used only for comparison und uses the id instead of comparing the whole object.

Perhaps my approach is totally wrong (it does not feel wrong), but i think optionComparePath would make ember-cli-selectize more flexible.

from ember-cli-selectize.

miguelcobain avatar miguelcobain commented on August 19, 2024

If optionValuePath would be "content.id" like you described, changing the selected option results in an ember-data error, because the property "article.parent" cannot be an integer but must be a valid model

I don't think this is true. If optionValuePath would be content.id, then:

  • value would be an integer (the model's id)
  • selection would be a valid model

If i compare the article.parent model (relationship) with the model, store.find returns, these are not equal (neither with Ember.isEqual nor with ===). I did not find out why yet.

When you do a this.get('model.parent'), and parent is a relationship, remember that you get a Promise, not the record. Don't know if you skipped this subject for brevity, but maybe this is the root of that problem.

from ember-cli-selectize.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.