Skip to content
This repository has been archived by the owner on Oct 2, 2019. It is now read-only.

setting chosen property of selected object as ngModel instead of the whole object #68

Closed
jrencz opened this issue May 25, 2014 · 12 comments · Fixed by #107
Closed

setting chosen property of selected object as ngModel instead of the whole object #68

jrencz opened this issue May 25, 2014 · 12 comments · Fixed by #107

Comments

@jrencz
Copy link

jrencz commented May 25, 2014

I'd like to ask if the module already is capable of the following and I just haven't found how or is it not yet possible:

Referring to the demo: I'd like for the module to be able to set only the email of the selected person as ngModel value, not the whole object (email, name, age) as it does now.

As I inspected the code it seems to be impossible looking at the line 62:

    var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);

and the way ctrl.select is used for both keyboard and pointer

What I'd like to propose is something closer to the ngOptions select as label for value in array syntax in the native angular select but label is not used in this case anyway since it's displayed using the template that is transcluded - so let's name it property as value in array. Example:

<ui-select ng-model="person.selected" theme="select2">
  <ui-match placeholder="Select a person in the list or search his name/age...">{{$select.selected.name}}</match>
  <ui-choices repeat="email as person in people | propsFilter: {name: $select.search, age: $select.search}">
    <div ng-bind-html="person.name | highlight: $select.search"></div>
    <small>
      email: {{person.email}}
      age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
    </small>
  </ui-choices>
</ui-select>
<p> Selected: {{ person.selected }} </p> <!-- I expect "Selected: foo@bar.com" instead of what it displays now: the whole object -->
@SimeonC
Copy link
Contributor

SimeonC commented May 26, 2014

Currently that shows: Selected: {"name":"Amalie","email":"amalie@email.com","age":12}
What you want should just be <p> Selected: {{ person.selected.email }} </p> which would output: Selected: amalie@email.com. Or is that not what you wanted? From what I read your getting a bit confused between model and view in angular. You want to have the whole object being set as the ngModel, but you can always choose to display a value of said object.

@jrencz
Copy link
Author

jrencz commented May 26, 2014

No, I'm quite sure I only want the email in my model. It may be that I didn't state it clear enough. Let's rephrase:

I'd like to modify a single property of my object and that property holds the user identifier, which is the email in my case. On the other hand I want for the user to be able go get rich suggestions with the user name (or maybe other data as well).
It's the similar case to using the basic HTML select field (or angular one btw): each option may have any text but it holds some value. Here each option can be rendered out of any of the properties it holds but the chosen value is always the whole object used to render the option and that's not what I want.

I of course can proxy this in my controller by creating some $scope property (as it is done in the demo: $scope.person) and after this property gets changed update my actual model but it's ui-select job in my opinion

@SimeonC
Copy link
Contributor

SimeonC commented May 26, 2014

Ah, OK. I see what you mean. Looking through the code ui-select uses ng-repeat code, which is much easier to read and simpler than the select code. If I get the time I'll try contribute, but that's some complex changes, I can see why they didn't include this in the first place.

@repo Owner/Contributors: Can I have a go at changing the ng-repeat expression into the select logic from angular?

@dimirc
Copy link
Contributor

dimirc commented Jun 28, 2014

@SimeonC could you open a PR and we start checking implications of this. Anyway I do see a real use case here

@j-hogue
Copy link

j-hogue commented Jun 30, 2014

@dimirc Please take a look at this Plunker, sample for setting ID.

http://plnkr.co/edit/Hijaxg?p=info

@dimirc
Copy link
Contributor

dimirc commented Jun 30, 2014

@j-hogue I just checked it and seams that it could work. Can you do a PR with the changes to review it better?

@SimeonC
Copy link
Contributor

SimeonC commented Jul 1, 2014

Realised that there's a much simpler way of doing this that I discovered during some of my other work with custom templates. Plunkr: http://plnkr.co/edit/svthAFvAmW7D0m8DYuA2?p=preview

I haven't fully tested this but AFAIK it should work as a workaround for @jrencz original use case.
Essence of it is the following directive and adding ui-select-field="email" onto the ui-select element.

app.directive('uiSelectField', function() {
  return {
    restrict: 'A',
    require: ['uiSelect', 'ngModel'],
    link: function(scope, element, attrs, ctrls) {
      var $select, ngModel;
      $select = ctrls[0];
      ngModel = ctrls[1];
      return ngModel.$parsers.push(function(value) {
        if(value[attrs.uiSelectField]) return value[attrs.uiSelectField];
        else return value;
      });
    }
  };
});

It might take me quite some time before I can get back around to doing the aforementioned PR I talked about.

@dimirc
Copy link
Contributor

dimirc commented Jul 13, 2014

@SimeonC yes, actually using parsers/formatters will be the way to go. As @jrencz proposed, maybe the field could be specified at the repeat expression instead of a new attribute:

Something like this:
person.email as person in people

I'm checking this right now, hope to have some update soon

@SimeonC
Copy link
Contributor

SimeonC commented Jul 13, 2014

That would work, the regex would be: ^\s*(([\s\S]+?)\s+as\s+)?([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$ then loop through match[2].split('.') in the parser to get the value erroring if the first doesn't match the new lhs (lhs = match[3]).

I've got some time now if you want me to run up a PR?

image

@dimirc
Copy link
Contributor

dimirc commented Jul 14, 2014

@SimeonC I did something similar. Take a look at PR #107 that I just created

All comments and suggestions are welcome. Also if you want to give a hand on something, some new tests will be perfect

@SimeonC
Copy link
Contributor

SimeonC commented Jul 14, 2014

Yea that looks about what I was going to do, I'll go make comments on that issue.

@mkamayd
Copy link

mkamayd commented May 2, 2015

I find this feature very cool. I think should be well documented.

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

Successfully merging a pull request may close this issue.

5 participants