I was wondering what is the best way to submit a form(iron-form) with the following structure:
Basic Polymer iron-form (starting point):
<form is="iron-form" method="post" action="/" id="basic">
<template is="dom-repeat" id="addresses" items="[[addresses]]">
<paper-input name="city" label="City" value="[[item.city]]"></paper-input>
<paper-input name="street" label="Street" value="[[item.street]]"></paper-input>
</template>
</form>
Target JSON payload structure after submit:
addresses: [
{ city: "X", street: "X" },
{ city: "Y", street: "Y" }
]
The way I am doing it now is using the dom-repeat's index and manually extending the payload at iron-form-presubmit phase. The idea behind this approach is coming from Spring-MVC where this is handled in a really neat way.
i.e.:
<form is="iron-form" method="post" action="/" id="basic">
<template is="dom-repeat" id="addresses" items="[[addresses]]">
<paper-input name="addresses[[[index]]].city" label="City" value="[[item.city]]"></paper-input>
<paper-input name="addresses[[[index]]].street" label="Street" value="[[item.street]]"></paper-input>
</template>
</form>
Thanks in advance!
Related
I have a custom view component that renders as three select lists, "Year", "Make" and "Model" and it's working well for me.
My problem lies when it's dynamically placed on a parent form... The tab order is out of whack and my research seems to indicate that is normal without a tabindex set.
Let's say I have something like this:
<input type="text" v-model="name" tabindex="1">
<my-widget v-if="someCondition"> </my-widget>
<input type="text" v-model="shop" tabindex="5">
How do I tell myWidget to set the tabindex for the selects inside my widget to 2,3,4?
Ideally I'd like to be able to use two of these widgets on the same page so hardcoding wont work.
Does anyone have any thoughts on the best way to assign tabindex inside a component?
You could have the tabindex as a prop on your my-widget component so that it can be dynamic. For example
my-widget component
<template>
<div>
<input type="text" :tabindex="tabindex"/>
<input type="text" :tabindex="tabindex + 1"/>
</div>
</template>
<script>
export default {
props: {
tabindex: {
type: Number,
required: false,
default: 1
}
}
</script>
so then your code will look like
<input type="text" v-model="name" tabindex="1">
<my-widget v-if="someCondition"
:tabindex="2"
> </my-widget>
<input type="text" v-model="shop" tabindex="5">
and if you add another one
<my-widget v-if="someCondition"
:tabindex="6"
> </my-widget>
I have the following partial:
<template is="dom-repeat" repeat="{{myItems}}">
One: <paper-input type="number" value="{{myValue1}}"></paper-input>
Two: <paper-input type="number" value="{{myValue2}}"></paper-input>
Three: <paper-input type="number" value="{{myValue3}}"></paper-input>
<template is="dom-if" if="[[_show(myValue1)]]">
Four: <paper-input value="{{myValue4}}></paper-input>
</template>
</tempalte>
myItems is an array with 4 elements, so, I can see 12 paper-inputs.
The problem is when I enter some text into first paper-input, the text appears into others paper-inputs (the firsts of each iteration).
Is there any way to bind different variables into dom-repeat template?
EDITED to use indices/ordinals instead of array values:
<template is="dom-repeat"
items="{{myItems}}" as="item">
One: <paper-input type="number" value="{{item.1}}"></paper-input>
Two: <paper-input type="number" value="{{item.2}}"></paper-input>
Three: <paper-input type="number" value="{{item.3}}"></paper-input>
<template is="dom-if"
if="[[_show(item.1)]]">
Four: <paper-input value="{{item.4}}></paper-input>
</template>
</template>
I'm using iron-form to send data to a Rails server. Currently the form is sending JSON similar to this:
{
"date": "January 1",
"name": "John Doe",
"company": "Whatever Inc."
}
But in order to receive it on the Rails end I need it to be formatted like this:
{
"userInfo": {
"date": "January 1",
"name": "John Doe",
"company": "Whatever Inc."
}
}
How do I nest the form data within the userInfo param? I tried using the iron-form-presubmit event listener but couldn't make it work.
Here is the code for my iron-form:
<form is="iron-form" id="form" method="post" action="url/for/api">
<input name="date" is="iron-input">
<input name="name" is="iron-input">
<input name="company" is="iron-input">
<div id="buttons">
<paper-button id="submit" raised onclick="_submit(event)">Save</paper-button>
<paper-button id="reset" raised onclick="_reset(event)">Reset </paper-button>
</div>
</form>
And the javascript:
<script>
Polymer({
is: 'my-view1',
});
function _submit(event) {
var form = Polymer.dom(event).localTarget.parentElement.parentElement;
form.submit();
}
function _reset(event) {
var form = Polymer.dom(event).localTarget.parentElement.parentElement;
form.reset();
}
</script>
from my understanding you could update the request body before the data gets submitted and transform the current data into an object/structure of your liking:
<form is="iron-form" on-iron-form-presubmit="_presubmit" id="form" method="post" action="url/for/api">
<input name="date" is="iron-input">
<input name="name" is="iron-input">
<input name="company" is="iron-input">
<div id="buttons">
<paper-button id="submit" raised onclick="_submit(event)">Save</paper-button>
<paper-button id="reset" raised onclick="_reset(event)">Reset </paper-button>
</div>
</form>
similar to how its done here, but changing the body entirely
function _presubmit(e) {
let body = this.$.form.request.body;
body = {"userInfo" : body };
}
Hope this helps a lil.
How to handle multiple input values with same name in meteor and expect array from events.
<input type="text" class="form-control valid" id="companyEmail" name="companyEmail[]">
By far the easiest way to scope events in Blaze templates is to define templates at the level at which you need to trap events.
If you have:
<template name="companyEmails">
{{#each companyEmail}}
<input type="text" class="form-control valid" id="companyEmail" name="companyEmail[]">
{{/each}}
</template>
Then if you attach an event handler to the companyEmails template you have to figure out which input was changed.
If you change this pattern to:
<template name="companyEmails">
{{#each companyEmail}}
{{> oneCompanyEmail}}
{{/each}}
</template>
<template name="oneCompanyEmail">
<input type="text" class="form-control valid" id="companyEmail" name="companyEmail[]">
</template>
Then you can attach an event handler to the lower level template and be guaranteed that you're getting the correct event on the correct object with the appropriate data context:
Template.oneCompanyEmail.events({
'input #companyEmail': function(ev,err){
var emailAddress = ev.target.value;
console.log(this); // will be the value of companyEmail from the #each
}
});
As always in Meteor you're probably working in a Template scope and creating those inputs dynamically.
if that is the case you need to create an event handler for the input and then capture the concurrent used input using "this", here's an example:
html file:
<template name="emailForm">
{{#each item in items}}
<input name="email" class="email" placeholder="enter email address">
<button class="addEmail">+</button>
{{/each}}
</template>
in your js file:
if(Meteor.isClient) {
Template.emailForm.events({
'click .addEmail': function(event) {
console.log(this);
}
});
}
take a look at what's comes out with "this" and find out how to extract your desired bit of data as it will represent only the clicked item.
Is there any possible method to create a form with one or more elements like:
<form action="{% url "foo" %}" method="POST">
<div id="report_item">
<input type="text" name="dontknow">
<input type="date" name="dontknow">
</div>
<div id="report_item">
<input type="text" name="dontknow">
<input type="date" name="dontknow">
</div>
</form>
And to get a dictionary from this form as below:
{data:
{1: {
text: 'bla', date: '2014-03-02'
},
{2: {
text: 'second text', date: '2014-03-01'
}
}
Not quite, but you probably want to look at formsets. That gives you a series of repeated forms, which you can output on the template by just iterating through. Once you've validated the POST data if you really need a dictionary you can do something like:
data = {i: form.cleaned_data for i, form in enumerate(formset.forms)}