Here is the code I'm working with:
<form id="myForm" action="form_action.asp">
First name: <input type="text" name="fname" value="Bob"><br>
Last name: <input type="text" name="lname" value="Smith"><br>
</form>
<button onclick="myFunction()">Submit</button>
<p id="demo"></p>
<script>
function myFunction() {
var x = document.getElementById("myForm").elements[1].value;
document.getElementById("demo").innerHTML = x;
}
</script>
I like how this works, but can't figure out how to define where and how the values are displayed. Ideally, I would like them to appear at specified places within a large block of text.
For example, with the values above, I could have the person put in their first name and last name, and then have the following show with the appropriate values in place:
[FirstName]'s last name is [LastName].
Right now, I can't figure out how to have the values they input show where I want them within other text.
Related
I'm using iron router to pass data to a bootstrap modal template. The modal contains a html form including many text inputs. The modal is re-used for 3 different features. I use a Session variable to keep track of which modal type is in use. Type 0 = blank form, type 1 = partial edit, type 2 = full edit. The form itself remains the same visually for all types. The only thing that changes is which input boxes contain a value.
For a type 1 edit only 2 boxes would contain values. For a type 2 edit all boxes would contain values. And the type 0 would be empty boxes.
// routes.js
Router.route('/mypage', function () {
var mtype = Session.get("mtype");
this.layout('myLayout');
this.render('my_popup', {to:'my_popup', data: function() {
switch (mtype) {
case 1:
return {box1:'box 1 text', box2:'box 2 text', box3:''};
case 2:
return {box1:'box 1 text', box2:'box 2 text', box3:'box 3 value'};
default:
return {box1:'', box2:'', box3:''};
}
}});
});
// main.html
<template name="myLayout">
{{> yield "my_popup"}}
</template>
<template name="my_popup">
<div class="modal fade" id="my_popup">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title label label-primary">Title</div>
</div>
<div class="modal-body">
<form class="js-form-submit" id="my_form" name="my_form">
<div class="form-group">
<input class="form-control" type="text" name="box1" maxlength="64" placeholder="something" value="{{box1}}"/>
</div>
<div class="form-group">
<input class="form-control" type="text" name="box2" maxlength="64" placeholder="something" value="{{box2}}"/>
</div>
<div class="form-group">
<input class="form-control" type="text" name="box3" maxlength="64" placeholder="something" value="{{box3}}"/>
</div>
</form>
</div>
<div class="modal-footer">
<button class="js-form-ok btn btn-success btn-sm">submit</button>
<button class="btn btn-warning btn-sm" data-dismiss="modal">cancel</button>
</div>
</div>
</div>
</div>
</template>
Initially I tried passing an object to the modal template that only contained the properties that would be displayed. That didn't overwrite existing input values so I had to use the same object for each modal type and use empty strings for unused properties. I tried calling the reset() method on the form prior to showing the modal. In that case it caused the entire template to stop re-rendering.
Prior to showing the modal I set the session variable to the type of modal that will be displayed.
Session.set('mtype', 1);
That triggers iron router into sending the proper data to the template, unused properties are cleared and the template successfully re-renders.
Unfortunately if I type in one of the html inputs the template does not reset its value when it's re-rendered. This seems to be related to the same problem I encountered with the reset() method. If the input contains custom text (value is typed) then the modal doesn't display the new data sent to the template when the Session variable is changed. It preserves the user entered text.
What's the best way to re-use a bootstrap modal form in meteor? Should I use a helper instead of iron router to get the data object? Something like...
{{#with getData}}
Why is the user entered text being preserved?
I've also tried using the defaultValue attribute instead of value. The same issue occurs with both attributes.
To test the bug:
open the web console
Session.set('mtype',1);
$('#my_popup').modal('show');
type something in the 3rd text box
click off the modal to hide it
Session.set('mtype',0);
$('#my_popup').modal('show');
You'll see that the value you typed is still visible despite having sent empty strings to each box.
Another way:
Session.set('mtype',2);
$('#my_form')[0].reset();
Session.set('mtype',1);
$('#my_popup').modal('show');
You'll see that none of the boxes contain values despite having sent new strings of text to each box.
The only solution I've found is to use defaultValue in the template and then loop through the form fields before modal is shown and set value = defaultValue.
<input class="form-control" type="text" name="box1" maxlength="64" placeholder="something" defaultValue="{{box1}}"/>
Template.my_popup.rendered = function() {
$("#my_popup").on('show.bs.modal', function() {
var elems = $('#my_form')[0].elements;
for (var i=0; i<elems.length; i++) {
if (elems[i].hasAttribute('defaultValue')) {
elems[i].value = elems[i].getAttribute('defaultValue');
}
}
});
};
view screen I am using https://amp.dev/documentation/components/amp-autocomplete/ and I am able show in results id and name concated in one string, but I need show only name and store id in hidden input.
code screen
<amp-autocomplete filter="substring" filter-value="name" min-characters="2" src="/ajax/get_active_clinics.php" class="name_autocomplete">
<input type="text" placeholder="Numele clinicii" name="clinic_name" id="clinic_name"
{literal}on="change:AMP.setState({clinic_name_validation: true, form_message_validation:true})"{/literal}>
<span class="hide"
[class]="formResponse.clinic_name && !clinic_name_validation ? 'show input_validation_error' : 'hide'">Clinica este obligatorie</span>
<template type="amp-mustache" id="amp-template-custom">
{literal}
<div class="city-item" data-value="ID - {{id}}, {{name}}">
<div class="autocomplete-results-item-holder">
<div class="autocomplete-results-item-img">
<amp-img src="{{link}}" alt="{{name}}" width="40" height="40"></amp-img>
</div>
<div class="autocomplete-results-item-text">{{name}}</div>
</div>
</div>
{/literal}
</template>
</amp-autocomplete>
You can use the select event on amp-autocomplete to get the event.value which will return the value of the data-value attribute of the selected item.
https://amp.dev/documentation/components/amp-autocomplete/#events
You can then call the split() string method on the result.
You'll need to modify the data-value in your mustache template like so:
<div class="city-item" data-value="{{id}},{{name}}">
Then add the following code to your autocomplete, this will assign the split values to 2 temporary state properties.
<amp-autocomplete
...
on="select: AMP.setState({
clinicName: event.value.split(',')[0],
clinicId: event.value.split(',')[1]
})"
>
Once these values are in state you can then access them using bound values. Note the [value] attribute, this will update the inputs value when state changes. It's worth mentioning that the change in value won't trigger the change event listener on your input here as it's only triggered on user interaction.
<input
type="text"
placeholder="Numele clinicii"
name="clinic_name"
id="clinic_name"
[value]="clinicName"
on="change:AMP.setState({
clinic_name_validation: true,
form_message_validation:true
})"
/>
Last thing you'll need to do is add the hidden input for Clinic ID, again this will need to be bound to the temporary state property clinicId.
<input
type="hidden"
name="clinic_id"
[value]="clinicId"
>
I'm trying to display a message that appears after the user has input some details into input boxes. Once they put in the info in the input boxes, the page should add the info to the multi-line text and then display the entire message on the webpage with the new info included. This code I have only displays the message without the input.
Here, I'm simply having the user put in the text in the box, then I tried to "parse" the input's value by giving it a variable name with a value within the code so it can be added as a property to the "libs" object. I have more to the message, but I can't even get this one sentence to process correctly.
<!DOCTYPE html>
<html>
<head>
<title>Madder Libs</title>
</head>
<body>
<div id="input">
<form>
<p>
<h4>Piece of clothing:</h4><input id="cloth" type="text" value=" " />
</p>
</form>
</div>
<script>
let clothes = document.getElementById('cloth').value;
let libs = {
a: clothes,
/*b: firstBodyPart,
c: secondBodyPart,
d: verbOne,
e: thirdBodyPart,
f: verbTwo,
g: firstNoun,
h: secondNoun,
i: verbThree,*/
};
let showThis = function()
{
let display = function(message)
{
let sayThis = `I wear a ${message.a} on sundays.`;
return sayThis;
}
document.getElementById('madlibs').innerHTML += "<br/>" + display(libs);
}
</script>
<div id="madlibs">
<button type="submit" onclick="showThis()">Show Message</button>
</div>
</body>
</html>
I want my message to be displayed including whatever the user put in the text box
Let's start by addressing why your sentence does not work. It is simply a matter of timing or in other words when things get executed. In your code (which isn't very well structured but onto that later) you execute
let clothes = document.getElementById('cloth').value;
at the very beginning of the script. In this case you are not obtaining some form of reference that would allow you to read the value at later stage but the actual value at the time. Since your input field has value attribute set to empty string, this is all you will ever get no matter how many times you execute the function later.
In order to get value of the input at the time of calling your method you would have to move it into the function itself.
But as I mentioned earlier your code is overall structured poorly so allow me to provide a few suggestions.
button of type submit by default executes submission of the form if placed within the form; you are not taking advantage of that (this has benefits such ability to submit form with "Enter" key e.g.
placing <script> in the middle of your document is poor choice as it blocks rendering of the rest of the document. Best options are to place it either within <head> when used with defer attribute or at the end of the document just before closing </body> tag.
Nesting your function within each other has not benefit here. You can easily define them independently and call one within the other if needed.
heading element <h4> cannot appear within <p> tag
Example
<!DOCTYPE html>
<html>
<head>
<title>Madder Libs</title>
</head>
<body>
<form action="/" onsubmit="return showThis()">
<div>
<label for="cloth">Piece of clothing:</label>
<input id="cloth" type="text" value="" />
</div>
<div id="madlibs"></div>
<div>
<button type="submit">Show Message</button>
</div>
</form>
<script>
// let's get references to our elements, so we don't have to
// do it multiple times
let clothes = document.getElementById('cloth');
let madlibs = document.getElementById('madlibs');
// let's define our functions
function display(message) {
let sayThis = `I wear a ${message.a} on sundays.`;
return sayThis;
}
function showThis() {
const clothesValue = clothes.value;
let libs = {
a: clothesValue,
/*b: firstBodyPart,
c: secondBodyPart,
d: verbOne,
e: thirdBodyPart,
f: verbTwo,
g: firstNoun,
h: secondNoun,
i: verbThree,*/
};
madlibs.innerHTML += "<br/>" + display(libs);
return false;
}
</script>
</body>
I am using jsviews for data binding:
My template
<script id = "ProfileTemplate" type="text/x-jsrender">
<input data-link="userVO.first_name" type="text">
<input type="reset" value="Reset" onclick="this.form.reset();">
</script>
My Form
<form name="profile-form" id="profile-form" action="profile.html">
<div id="flightEditDetail"></div>`enter code here`
</form>
<script>
var template = $.templates("#ProfileTemplate");
template.link("#flightEditDetail", profileJSON);
</script>
The template binds the value correctly. I changed the value in the text field and clicked on reset button. The text field becomes empty but I want the value that was rendered on page load.
Why does reset() function not work properly with jsviews data-link
reset() will revert the the intial/default value set in the value property: <input value="initialValue" />
For your case you could set the 'statically defined' value to the initial data value:
<input data-link="userVO.first_name" type="text" value="{{:userVO.first_name}}"/>
or better - attribute encode the initial value to avoid injection attacks:
<input data-link="userVO.first_name" type="text" value="{{attr:userVO.first_name}}"/>
The result is that the user will see the original value. However the reset action will only change the UI value, not the value in your underlying data that you are linking to. (See http://bugs.jquery.com/ticket/11043 for a related issue/concern in jQuery). So you would probably be better off not using reset() but instead cloning your initial data, and using $.observable(userVO).setProperty(originalUserVO) to revert.
I have this code: <p class = "foo">Text</p>
And I also have a form: <form action = "XXX.php" method = post></form>
However, how can I get the value of the <p> when I submit it, as the <p> element can be changed.
So what I mean is to be able to post the value of the <p> when the user submits the form, and to be able to access it from that php file with: $_POST['foo'];
Thanks, I have tried to be as clear as possible.
You have to use Javascript for that
A jQuery function that will work
$("form").submit(function(){
var value = $("p").html();
// If foo already exists
if( $("[name=foo]").length > 0 )
{
$("[name=foo]").val(value);
}
else
{
var input = $("<input />", { name : "foo",
value : value ,
type : "hidden" });
$(this).append(input);
}
});
Use
<input type="hidden" value="something" name="something" id="something" />
and when you change inner html of <p> change the value of hidden input.
I think your best bet is to make it an input with readonly enabled, and style to to look like a <p>. It's better then trying to add it to the POST parameters with JavaScript.
Here's a quick example. I bet it could still be improved with a few extra CSS quirks, experiment a bit.
The easiest thing to do is set the value of a hidden form field when you change the contents of your <p>.
Alternatively, you can get its contents and post with JavaScript.
For text you need to use input field:
<input type="text"/>
Form fields should must have an id:
<input type="text" id="pewpew" class="foo"/>
I would go with:
<input type="text" id="pewpew" class="foo" value="default text goes here"/>
OR
Go with different workarounds, like setting form's hidden elements on the fly, etc.
You can create hidden field on the fly and set its value on form submit. Like this:
<form id="form" action="/somewhere" method="post">
<p>Some text</p>
<input type="submit" value="Submit"/>
</form>
<script type="text/javascript">
var form = document.getElementById('form');
form.onsubmit = function()
{
var p = this.getElementsByTagName('p')[0];
if (!document.getElementById('pval'))
{
var pinput = document.createElement('input');
pinput.setAttribute('type', 'hidden');
pinput.setAttribute('id', 'pval');
pinput.setAttribute('name', 'p');
this.appendChild(pinput);
}
document.getElementById('pval').value = p.innerHTML;
return true;
}
</script>
Works, i've tested.