Template Helper Functions - templates

Is it possible to pass a variable into a template helper function to determine which object is returned, without creating a new template for each? Something like this, maybe?
{{#each frame}}
<p>{{name}}</p>
<p>{{description}}</p>
{{/each}}
Template.templateName.helpers({
classic : [
{
name : 'first option',
description : 'this is option 1'
},
{
name : 'second option',
description : 'this is option 2'
}],
versions : [
{
name : 'first option',
description : 'this is option 1'
},
{
name : 'second option',
description : 'this is option 2'
}],
{
'frame' : function(boardSpecs){
if (boardSpecs[0] == "classic"){
return classic;
}
else if (boardSpecs[0] == "versions"){
return versions;
}
}
})

You can probably play with {{#if}}.
For example only with classic and versions:
Template:
{{#each frame}}
{{#if classic.active}}
<p>{{classic.name}}</p>
<p>{{classic.description}}</p>
{{/if}}
{{#if versions.active}}
<p>{{versions.name}}</p>
<p>{{versions.description}}</p>
{{/if}}
{{/each}}
Helpers:
Template.templateName.helpers({
active: {
classic: function(){ return Session.get("active") == "classic"; }
versions: function(){ return Session.get("active") == "versions"; }
},
classic : [
{
name : 'first option',
description : 'this is option 1'
},
{
name : 'second option',
description : 'this is option 2'
}],
versions : [
{
name : 'first option',
description : 'this is option 1'
},
{
name : 'second option',
description : 'this is option 2'
}]
})
Then you can set Session.set("active", "name of the one you want") when you need to change view.

Related

Quick reply in react native gifted chat not showing

I have the following setup done in my code, however the quick replies are not showing. Below shown is my state object and render code. [The quick reply is not showing, am i missing something in the code ? 1
state = {
messages : [
{
_id: 1,
text: 'My message',
"quickReplies":[
{
"contentType":"text",
"title":"Yes",
"imageUrl":"http://example.com/img/yes.png"
},
{
"contentType":"text",
"title":"No",
"imageUrl":"http://example.com/img/no.png"
}
]
}],
}
My Render method is as follows
render() {
return (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<HeaderIconExample color ='#1976d2' title ={"Digital Assistant"} />
<GiftedChat
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
onQuickReply={quickReply => this.onQuickReply(quickReply)}
user={{
_id: 1
}}
/>
<KeyboardSpacer />
</View>
);
}
However when the app executes, only the text property of the message object is shown. Please see below image for more details.
The format of quick reply is wrong:
You should change it to something like this
message: [{
_id: 1,
text: "text",
createdAt: new Date(),
user: user,
quickReplies: {
type: 'radio' // or 'checkbox'
values: [{
title: "yes"
value: "yes"
},{
title: "no"
value: "no"
}]
}
}]

Emberjs Power select dynamic options and selectors

I'm struggling a bit with the proper pattern to use here. I have a model which represents a power selector called selector, each selector has a hasMany with selectorOption which makes up the options for the selector
I then have a dashboardItem model which loops over each selector and implements it.
route.js
export default Route.extend({
model(params) {
return RSVP.hash({
dashboard: get(this, 'store').findRecord('dashboard', params.dashboard_id),
selectors: get(this, 'store').findAll('selector'),
});
},
setupController(controller, models) {
controller.setProperties(models);
},
});
template.hbs
{{#each selectors as |selector|}}
<div class="column is-12 object-item">
<div class="card">
<header class="card-header">
<p class="card-header-title">
{{selector.title}}
</p>
</header>
<div class="card-content">
{{#power-select-multiple
placeholder="Vision"
options=selector.selectorOptions
searchEnabled=false
onchange=(action 'something...') as |option|}}
{{option.title}}
{{/power-select-multiple}}
</div>
</div>
</div>
{{/each}}
I'm not sure what to do on the onchange, either with a custom function or using built in tools of power-select.
Each selector is a multi-selector.
This works correctly to the point that I can create any number of selectors and they display on the front end with their correct options as expected.
How should I go about saving the options the users choose against the dashboardItem?
Here is a section from the database which shows the models and their relationships. Note there is currently no relationship between a selector and a dashboardItem (Maybe there should be though?)
{
"selectorOptions" : {
"-Kyc7on207d_IxnNw2iO" : {
"title" : "Apple",
"vision" : "-Kyc7nG9Bz3aEGLked8x"
},
"-Kyc7qC9_uxFgXP9c7hT" : {
"title" : "Orange",
"vision" : "-Kyc7nG9Bz3aEGLked8x"
},
"-Kyc7qqZPMikoG1r3r5g" : {
"title" : "Bannana",
"vision" : "-Kyc7nG9Bz3aEGLked8x"
},
"-Kyc7uZu8MTfUdH70cBR" : {
"title" : "Blue",
"vision" : "-Kyc7rtTPTMJxAPacg-L"
},
"-Kyc7vJC3ImzVOEraALx" : {
"title" : "Green",
"vision" : "-Kyc7rtTPTMJxAPacg-L"
},
"-Kyc7wCrqDz8CD_I-dYy" : {
"title" : "Red",
"vision" : "-Kyc7rtTPTMJxAPacg-L"
}
},
"selectors" : {
"-Kyc7nG9Bz3aEGLked8x" : {
"title" : "Fruits",
"selectorOptions" : {
"-Kyc7on207d_IxnNw2iO" : true,
"-Kyc7qC9_uxFgXP9c7hT" : true,
"-Kyc7qqZPMikoG1r3r5g" : true
}
},
"-Kyc7rtTPTMJxAPacg-L" : {
"title" : "Colours ",
"selectorOptions" : {
"-Kyc7uZu8MTfUdH70cBR" : true,
"-Kyc7vJC3ImzVOEraALx" : true,
"-Kyc7wCrqDz8CD_I-dYy" : true
}
}
}
}
The solution was to not fight against relationships with basic array storage.
For example
Base
export default Model.extend({
title: attr('string'),
visionOptions: hasMany('vision-option'),
});
Bases Options
export default Model.extend({
title: attr('string'),
vision: belongsTo('vision'),
});
The model to save the selected objects on
export default Model.extend({
//...
visionOptions: hasMany('vision-option', {async: true}),
//...
});
The component to handle saving, and selecting the correct objects
export default Component.extend({
tagName: "",
classNames: "",
selectedVisions: computed('dashboardItem.visionOptions', function () {
const visionId = this.get('vision.id');
const options = this.get('dashboardItem.visionOptions');
return options.filterBy('vision.id', visionId);
}),
actions: {
addVision(newList) {
let dashboardItem = get(this, 'dashboardItem');
let options = get(this, 'selectedVisions');
options.forEach(function (me) {
if (!newList.includes(me)) {
dashboardItem.get('visionOptions').removeObject(me);
}
});
newList.forEach(function (me) {
if (!options.includes(me)) {
dashboardItem.get('visionOptions').pushObject(me);
}
});
dashboardItem.save().then(() => {
dashboardItem.notifyPropertyChange('visionOptions')
});
}
}
});
Template to render power-select
{{#power-select-multiple
placeholder=""
options=vision.visionOptions
searchEnabled=false
selected=selectedVisions
onchange=(action 'addVision') as |vision|}}
{{vision.title}}
{{/power-select-multiple}}
This allows there to be an unknown number of "visions", with an unknown number of "visionObjects" to be loaded and saved.
The notifyPropertyChange is required to update the computed property so the frontend renders when a user adds or removes a selected object. This is only awkward because there isn't a direct known database key.

How to add conditional operator with string in react

I'm making a list using React-JS. I'm struggling to sort the data using conditional operator.
There is a list of friends (with inputs for name and gender).
Data should be sorted according to gender.
When you click the 'male' button, only the item with 'male' value should show and the value with 'female' should be hidden.
When you click the 'female' button, only the item with 'female' value should show and the value with 'male' should be hidden.
I added the conditional operator but it didn't work. The conditional operator with 'string' will work in React?
style={{ display : this.state.male && friend.gender == "male" ? "block" : "none" }}
List.js
class FriendList extends Component {
constructor(props, context) {
super(props, context);
this.state = {
male: false,
female: false
}
}
maleButton(e) {
this.setState({
male: !this.state.male
});
}
femaleButton(e) {
this.setState({
female: !this.state.female
});
}
render() {
return (
<div>
<button onClick={this.maleButton.bind(this)}>Male</button>
<button onClick={this.femaleButton.bind(this)}>Female</button>
<ul className={styles.friendList}>
{
this.props.friends.map((friend, index) => {
return (
<FriendListItem
key={index}
id={index}
name={friend.name}
starred={friend.starred}
gender={friend.gender}
style={{ display : this.state.male && friend.gender == "male" ? "block" : "none" }}
{...this.props.actions} />
);
})
}
</ul>
</div>
);
}
}
FriendList.propTypes = {
friends: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
};
export default FriendList;
The data will be like this:
const initialState = {
friendsById: [{
name: 'Theodore Roosevelt',
starred: true,
gender: 'male'
}, {
name: 'Abraham Lincoln',
starred: false,
gender: 'male'
}, {
name: 'George Washington',
starred: false,
gender: 'male'
}, {
name: 'Hillary Clinton',
starred: false,
gender: 'female'
}]
};
Maybe change your approach a little bit and filter results first:
this.props.friends
.filter(friend =>
this.state.male && friend.gender === 'male' ||
this.state.female && friend.gender === 'female'
)
.map((friend, index) => ...)
Unless you need to display both male and female genders at the same time, another suggestion I give you is to remove duplication per se (with both boolean values in state) and store a single gender value as string for example. With that, filtering approach becomes even easier to understand:
this.props.friends
.filter(friend => friend.gender === this.state.gender)
.map((friend, index) => ...)
You can use .filter for that purpose instead of .map.For that you can simply do as:
{
this.props.friends.filter((friend, index) => {
if((this.state.male && friend.male) || (this.state.female && friend.female)) {
return (
<FriendListItem
key={index}
id={index}
name={friend.name}
starred={friend.starred}
gender={friend.gender}
style={{ display : "block" }}
{...this.props.actions} />
);
}
})
}

Ember js to work with HATEOAS REST API

I have a REST endpoint "http://localhost:8080/customers" which I would like to hook to my Ember JS app.
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.extend({
url: 'http://localhost:8080/customers'
})
});
REST Payload
{
"_links" : {
"search" : {
"href" : "http://localhost:8080/customers/search"
}
},
"_embedded" : {
"customers" : [ {
"id" : 2,
"firstName" : "Jim",
"lastName" : "Smith",
"_links" : {
"self" : {
"href" : "http://localhost:8080/customers/2"
}
}
}, {
"id" : 1,
"firstName" : "Jimmy",
"lastName" : "Jones",
"_links" : {
"self" : {
"href" : "http://localhost:8080/customers/1"
}
}
} ]
}
}
I keep on getting this error. This is my second week on Ember JS. To be honest this is a lot harder than I imagined. Not very easy to debug or understand.
Error while loading route:
TypeError: undefined is not a function
at App.CustomersRoute.Ember.Route.extend.model
Essentially you need to transform your data into this format using a custom serializer:
{
"customers" : [
{
"id" : 2,
"firstName" : "Jim",
"lastName" : "Smith"
}, {
"id" : 1,
"firstName" : "Jimmy",
"lastName" : "Jones"
}
]
}
You'll want to read https://github.com/emberjs/data/blob/master/TRANSITION.md which explains how to use extractSingle, extractArray, normalize, normalizeHash.
You're particular example looks close to the api's example:
http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_extractArray
App.CustomerSerializer = DS.ActiveModelSerializer.extend({
extractArray: function(store, type, payload) {
// do your own implementation and return that, or modify it slightly
// and do the default implementation
return this._super(store, type, payload);
},
});

ExtJS 4.1.0 proxy returns update api instead of create

I was working on a code which was about integrating ExtJS 4 and Django. The link is:
https://github.com/diegocmsantos/extjs4-tdc2011-django
It works fine on ExtJS 4.0.0. But when I upgrade to 4.1.0 it's proxy returns update api instead of create.
I have added the 'idProperty' parameter to the Model, but still gives me the same result.
Model class:
Ext.define('TDC2011.model.Contact', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields : [
{ name : "id", type : "int", mapping : "#id" },
{ name : "name", type : "string"},
{ name : "phone", type : "string"},
{ name : "email", type : "string"}]
});
Store Class:
Ext.define('TDC2011.store.Contacts', {
extend: 'Ext.data.Store',
model: 'TDC2011.model.Contact',
autoLoad: true,
pageSize: 35,
autoLoad: {start: 0, limit: 35},
proxy: {
type: 'ajax',
api: {
read : 'contact/view.action',
create : 'contact/create.action/',
update: 'contact/update.action/',
destroy: 'contact/delete.action/'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: false,
root: 'data'
},
listeners: {
exception: function(proxy, response, operation){
Ext.MessageBox.show({
title: 'REMOTE EXCEPTION',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
Is there anyone who knows the main cause of problem?