Binding expression to interpolation?


#1

Is there a work around to bind an interpolation to an expression?

<ion-segment [(ngModel)]="something" (ionChange)="onChange($event)">
  <ion-segment-button *ngFor="let some of things" value="{{some | json}}" [myDataToBind]="{{some}}">
    {{some.label}}
  </ion-segment-button>
</ion-segment>

Possibly with ion-segment, or any custom ionic component? I really just want to send the entire object over, which I can do in the above with using a pipe on value, but I rather use a proper of the object as a string.


#2

Can you describe a bit more what you’re trying to achieve? I’m having a hard time understanding how that proposed syntax should be parsed.


#3

Sure - what I’m really trying to do is when a user selects an option - ie. ion-option, ion-segment-button, etc - the onChange/ionChange/custom event would not only send the value of the option, but carry an entire object over as well.

So in this example, if you select an ion-segment-button, I want to pass a big ole json object to the onChange event, somehow … dynamically. Sounds foolish as I say it, not not even sure possible.


#4

If I’m understanding you correctly, what happens if you swap [value]="some" in where you currently have value="{{some | json}}"?


#5

yeah, for value I just really want a string, or value="{{some.slug}}" so I can track what options are being selected instead of passing the entire object in.

normally I thought data-some="{{some}}" would work in some way as a data attribute, but not wrapping my head around it.


#6

This seems contradictory to me. You say you want to pass an entire object, [value] offers you a way to do that, but then you don’t want to do that. I’m baffled at this point.


#7

What about making your function (ionchange)=“onchange($event, this.some)” or ($event, some)?
Might be able to get the result you want by including the original object?


#8

I will try this out, didn’t occur to me I could pass more than one parameter. Well, how would I however? Some is part of the ngFor loop within the ion-segment-button, whereas the event is being declared at the ion-segment? Nonetheless I will give it a go.


#9

Fair enough. I wasn’t able to set a default value for the options of ion-segment by passing in a whole object. I suppose I could also try and see if ``[selected]=“someCheck($event)”``` it does the trick.


#10

Make sure you are using the exact same object, not a clone with similar properties. See framework #6225 for more context.


#11

This may be a hacky way to get this result, but (for me also), ion-option and ion-select are a little tricky.
I have an ion-select that pulls up a list of venues. The page’s constructor has an object called this.venues. My html [(ngModel)] =“venue”, and change event is (ngModelChange)=“selChange($event, ‘venues’)”.
here’s the html
ion-select name=“venue” [(ngModel)]=“venue” (ngModelChange)="selChange($event, ‘venues’)"
ion-option *ngFor=“let venue of venues”
{{venue}}
ion-option
ion-select

In my case, the page/component is called TicketsPage.
My function on TicketsPage.ts

selChange(event:any, x) {
console.log(this[x]);
}

So console.log(this[x]) is console.log(TicketsPage[this.venues], and i get this.venues, the original object).Hacky, but it works. At that point, you have the original object to do what you will.


#12

There has got to be a cleaner solution for your situation. Can you share more code so that we can understand better what’s going on?


#13

yeah. Just realized there was a much simpler approach and changed my reply, but it still gets ‘this’ involved. Not good, but it’s the only thing I can come up with.


#14

Thanks for spending time on it, so here’s my dom -

<ion-segment [(ngModel)]="something" (ionChange)="onChange($event)">
  <ion-segment-button *ngFor="let item of somethings" value="{{item | json}}">
    {{item.label}}
  </ion-segment-button>
</ion-segment>

Now when you select an option, item is bound to something as the correct json.

But in my constructor, I just want to set the default item by object, not string field. compareWith doesnt work with ion-segment.

constructor(private svc: ServiceProvider) {
  svc.getData().then(data => {
      this.something = data[0]; 
      this.somethings = data; // an array of objects
  });
}

I suspect data[0] is NOT equal to the DOMs value="{{item | json}}"? So I guess my real problem is setting the default value for the ion-segment when value is an object.


#15

So the work around is that I set each ion-segment-button value="{{item.slug}}", and then I just find which object it is by filtering and reducing from the original data when it’s selected -

getRaw(o): Promise<any> {
    let tmp = this.somethings.filter(item => item.slug === (o && o.value)).reduce((acc, cur) => cur, {});
    return Promise.resolve(tmp);
}

Just feels bloated…


#16

I don’t understand the fixation on making the value a string by passing item to the json pipe, but if you insist on doing that, you are going to have to set the default value similarly. Furthermore, that seems very brittle, because you have to rely on the JSON stringification process working exactly the same way.

What you say you are fundamentally trying to do (use an object as the default value) is possible. For example,

optionsPlatos: FoodItem[] = [
  {name: "Sencillo", price: 100},
  {name: "Normal", price: 200},
];

plato: FoodItem;

constructor() {
  this.plato = this.optionsPlatos[1];
}

<ion-select [(ngModel)]="plato">
  <ion-option *ngFor="let dish of optionsPlatos" [value]="dish">{{dish.name}}</ion-option>
</ion-select>

You should see “Normal” as the default value of the select.


#17

Apologies for making you go around in circles - didnt wrap my head around your prior claim about [value]doing the trick. I thought it was a typo, because “dish” wasn’t being declared anywhere inside my .ts file. So it appears that when you set value as an input, [value] - the expression is coming from within the *ngFor directive. :dizzy_face: whoosh


#18

That’s one possibility. It can be an expression involving both template variables (such as something coming from an ngFor) or a property (or even the result of a function) defined in the controller. Generally you want to keep it as simple as possible for both performance (these get evaluated a lot of times due to change detection) and readability, but any input properties can be full-on template expressions. For more detail, see the template expression section of the syntax docs.