Set focus for paper-input via radio button - input

In Polymer (1.0), how can I set the focus of the iron-input when (as example) radiobutton 'radio1' is selected.
<div>
<div>Title:</div>
<paper-radio-group>
<paper-radio-button name="radio1">Radio1Label</paper-radio-button>
<paper-radio-button name="radio2">Radio2Label</paper-radio-button>
</paper-radio-group>
<paper-input-container>
<input is="iron-input">
</paper-input-container>
</div>

You will need to bind a click event to radio1:
<paper-radio-button name="radio1" on-click="_setInputFocus">Radio1Label</paper-radio-button>
Then define the function _setInputFocus so that it selects the input and sets the focus to it:
<script>
Polymer({
is: 'the-name-of-your-element',
_setInputFocus: function () {
this.$$("input").focus();
}
});
</script>
EDIT: Now we want the input disabled until the user selects the radio button. So we give the iron-input the disabled attribute:
<paper-input-container>
<input is="iron-input" disabled>
</paper-input-container>
Then we change our JavaScript function so that we remove the disabled attribute and sets the input focus:
<script>
Polymer({
is: "focus-test",
_setInputFocus: function () {
var inputElement = this.$$("input"); // grab the element
inputElement.toggleAttribute("disabled", false); // remove the disabled attribute
inputElement.focus(); // set the focus to this input
}
});
</script>

You could also use the <paper-input> instead of the <paper-input-container> element and then use
setTimeout(function() {
this.$.tabname.inputElement.focus()
}.bind(this), 200);
in your function. (The set timeout is sometimes necessary because if another element had focus and is about to close (e.g. an iron-dropdown) then you would have to wait for this to finish before giving focus to the input)

Related

In Vue, how to get the content of a textarea?

I want to keep the value of a variable identical with the content of a textarea.
I don't want to use v-bind or v-model, because I have already bound the textarea with another value.
This is a notebook app, and the textarea is used to display the content of a note, so it has been bound using v-bind with a note object, like
<textarea cols="30" rows="3" v-bind:value="note"></textarea>
Now, I want to add the "edit note" functionality. So when the content of the textarea changes, I want to store its value into a variable, and when the "submit" button is clicked, I pass the value of the variable, which contains the new content of the note, to backend to update the note.
My question is, how to store the textarea's content into the variable after each time the content changes?
I think I cannot use v-model because this way the note will be changed right after the content of the textarea is modified (though not sent to backend), but this is not what I want. What I want is the note to be changed only after the "submit" button is clicked. Thus, I cannot use v-model
Should I use v-on:change? If so, how to get the content of the textarea?
Like,
<textarea v-on:change="updateTheVariable(I need to get the content of the textarea here)"> ... </textarea>
methods: {
updateTheVariable(content of the textarea) {
this.variable = content of the textarea
}
}
Thanks
I'm assuming this thing only shows up when you click some kind of edit button which is why you don't want to alter note so try something like this instead
<button type="button" v-if="!editMode" #click="editNote">Edit</button>
<form v-if="editMode" #submit="handleSubmit">
<fieldset :disabled="saving">
<textarea v-model="editingNote"></textarea>
<button type="submit">Edit</button>
</fieldset>
</form>
export default {
data: () => ({
note: 'whatever', // maybe it's a prop, maybe assigned later, doesn't matter
editMode: false,
editingNote: null, // this will be used to bind the edited value
saving: false
}),
methods: {
editNote () {
this.editingNote = this.note
this.editMode = true
this.saving = false
},
async handleSubmit () {
this.saving = true // disables form inputs and buttons
await axios.post('/notes/update', { note: this.editingNote}) // just an example
this.note = this.editingNote // or maybe use data from the response ¯\_(ツ)_/¯
// or if it's a prop, this.$emit('updated', this.editingNote)
this.editMode = false
}
}
}
As #Phil indicated in a deleted post, the right way to do it is
<textarea #input="updateTheVariable($event.target.value)"></textarea>
.
.
.
methods:{
updateTheVariable(value){
this.variable = value
}
}

set value of input programatically doesn't refresh component DOM

I have an input which is bidden to property message. I have a set button , which I use for changing of input value programmatically. When the button is pressed, value of input is correctly changed to 'xxxx'. when I press clean button after that , the input is correctly cleaned but when I repeat pressing set and clean again the input does not get cleared anymore.
Working example is here:
https://codepen.io/dan-ouek/pen/rNBjxRO
<div class="container">
<div id='root' class="box">
<input ref="templateFilter" type='text' id='input' v-model='message'>
{{ message }}
<button #click="set">set</button>
<button #click="clean">clean</button>
</div>
</div>
new Vue({
el: '#root',
data: {
message: 'Hello Vue'
},
methods: {
set: function () {
let element = this.$refs.templateFilter
Vue.set(element, 'value', 'xxxx')
}, clean: function () {
this.message = ""
}
}})
Questions:
1) Is it possible to change input programmatically without working with bidden property value? Something like direct DOM manipulation:
let element = document.getElementsByClassName("templateFilter")[0]
element.value = 'xxxxx'
but with proper component refresh?
2) Why is the {{ message }} not refreshed after calling set method?
Why is the message not refreshed after calling set method?
When you type something on your input the message data gets updated via an event handler BUT when you set it programmatically the event handler is NOT triggered and that's why message was not getting updated / refreshed....
Solution :
a short solution to your issue would be just to mutate the message value this.message = "xxxx" but if you insist on making that programmatically you have to trigger the input event :
set: function() {
let element = this.$refs.templateFilter
Vue.set(element, 'value', 'xxxx')
element.dispatchEvent(new Event('input'))
}
Here is a Demo : codepen

You may have an infinite update loop in a component render function using click event conditional rendering

I am rendering two texts based on a condition and be able to pass methods to the click event based on the condition. The default text is ADD TO COLLECTION because initially hasPaid property is false. Once payment has been made, I want to set that property to true
The function addToCollection first opens a modal, on the modal, the handlePayment function is implemented. I have been able to conditionally render the div to show either ADD TO COLLECTION or DOWNLOAD using v-on="". I also return hasPaid property from the handlePayment function.
<div class="float-right peexo-faded-text card-inner-text" :face="face" v-on="!hasPaid ? {click: addToCollection} : {click: handleDownload(face)}">
{{!hasPaid ? 'ADD TO COLLECTION': 'DOWNLOAD' }}
</div>
data: function () {
return {
hasPaid: false,
}
},
addToCollection(){
this.showcollectionModal = true;
},
handlePayment(){
this.showcollectionModal = false;
let accept = true;
this.showpaymentsuccessmodal = true;
//this.hasPaid = true;
return {
hasPaid: accept
}
},
I want to be able to set hasPaid property on the handlePayment function for the render function to pick it, so that the handleDownload function can then work.
The last section of this bit is going to be problematic:
v-on="!hasPaid ? {click: addToCollection} : {click: handleDownload(face)}"
When hasPaid is true it will invoke the method handleDownload immediately. That is, it will be called during render, not when the <div> is clicked.
You could fix it by 'wrapping' it in a function:
{click: () => handleDownload(face)}
I've used an arrow function in my example but you could use a normal function if you prefer.
Personally I wouldn't try to do this using the object form of v-on.
My first instinct is that you should consider just having two <div> elements and use v-if to decide which one is showing.
If you did want to use a single <div> I would put the click logic in a method. So:
<div class="..." :face="face" #click="onDivClick(face)">
Note that despite the apparent syntactic similarity to the way you defined your click listener this won't invoke the method immediately.
Then in the methods for the component:
methods: {
onDivClick (face) {
if (this.hasPaid) {
this.handleDownload(face)
} else {
this.addToCollection()
}
}
}

Dijit.tree extension with radio buttons submitting the wrong value

I've written a class that extends dijit.Tree to include a radio button alongside each node. I'm using it in a form to show a folder tree from which the user can select a folder. Here is the code:
define("my/Tree/RadioButton",
['dojo/_base/declare', 'dijit/Tree', 'dijit/form/RadioButton', 'dojo/dom-construct', 'dojo/_base/connect', 'dojo/on', 'dojo/_base/lang'],
function (declare, Tree, RadioButton, domConstruct, connect, on, lang){
var TreeNode = declare(Tree._TreeNode, {
_radiobutton: null,
postCreate: function(){
this._createRadioButton();
this.inherited(arguments);
},
_createRadioButton: function(){
this._radiobutton = new RadioButton({
name: this.tree.name,
value: this.tree.model.store.getIdentity(this.item) + '',
checked: false
});
domConstruct.place(this._radiobutton.domNode, this.iconNode, 'before');
if (this.tree.model.store.hasAttribute(this.item, 'checked')) {
var attrValue = this.tree.model.store.getValue(this.item, 'checked');
if (attrValue === true) {
this._radiobutton.set('checked', true);
}
}
connect.connect(this._radiobutton, 'onClick', this, function(){
// set any checked items as unchecked in the store
this.tree.model.store.fetch({
query: {checked: true},
onItem: lang.hitch(this.tree.model.store, function(item){
console.log('found checked item ' + this.getValue(item, 'name'));
this.setValue(item, 'checked', false);
})
});
// check the one that was clicked on
var radioValue = this._radiobutton.get('value');
this.tree.model.store.setValue(this.item, 'checked', true);
});
}
});
return declare(Tree, {
_createTreeNode: function(/*Object*/ args){
return new TreeNode(args);
}
});
});
The issue is that when the form is submitted, the value that is submitted is always the value of the first radio button that was selected, even if other radio buttons are subsequently clicked on.
I can see by inspecting the dom that the value attribute for the checked radio button has the correct value. But what gets submitted is always the initially selected value.
I have a similar class that uses the checkbox widget instead and that one works fine.
Edit based on some feedback I created an even simpler version of this class that doesn't track the checked state using attribute in the store:
define("my/Tree/RadioButton",
['dojo/_base/declare', 'dijit/Tree', 'dijit/form/RadioButton', 'dojo/dom-construct'],
function (declare, Tree, RadioButton, domConstruct){
var TreeNode = declare(Tree._TreeNode, {
_radiobutton: null,
postCreate: function(){
this._createRadioButton();
this.inherited(arguments);
},
_createRadioButton: function(){
this._radiobutton = new RadioButton({
name: this.tree.name,
value: this.tree.model.store.getIdentity(this.item) + '',
checked: false
});
domConstruct.place(this._radiobutton.domNode, this.iconNode, 'before');
}
});
return declare(Tree, {
_createTreeNode: function(/*Object*/ args){
return new TreeNode(args);
}
});
});
but even this still has the same issue - whichever radio button the user clicks on first is the value that will be submitted, regardless of what other buttons are subsequently clicked.
I managed to workaround this issue by hooking on to the onchange event for the radio buttons. The hook explicitly sets checked to false on the unchecked radio button, which seems to fix the problem. I'm unsure why this is required though.
I have this exact same problem. It used to work in older Dojos. Specifically, ALL of the radioButtons incorrectly return true on "dijit.byId("whatever").checked" during the onClicked function. When checked manually after the onClicked function finishes using FireBug console, the above property returns the correct values. I think it is a bug, and I only worked around it by having a different onClicked function for each button, like so:
<form id="locateForm">
<label for="locate">Locate:</label><br />
<input type="radio" dojoType="dijit.form.RadioButton" name="locate" id="locateAddress" value="Address" checked="checked" onClick="enableLocate1();" />
<label for="locateAddress">Address</label>
<input type="radio" dojoType="dijit.form.RadioButton" name="locate" id="locatePlace" value="Place" onClick="enableLocate2();" />
<label for="locatePlace">Place</label>
</form>

onfocus event not firing on dojo dijit FilteringSelect

I have a page with 7 dijit FilteringSelect widgets that I want to connect to stores fetched from the server if the user clicks on the widget or the widget otherwise gains focus. I want the event to fire one time.
If I add onfocus="loadDropDown(this)" to my markup, it executes every time the widget gains focus, as you would expect.
I'm trying to use dojo to fire the event one time using on.once(). The function to use dojo event handling is running but the event handler function never gets called when a widget gains focus.
Any pointers?
This is my markup
<select data-dojo-type="dijit.form.FilteringSelect"
type="text" intermediateChanges="false"
data-dojo-props="required:false, pageSize:20, placeholder: '---'"
scrollOnFocus="true" name="CJ1lxA" style="width: 40em;"
id="searchAgency">
</select>
This is to regester the events
function registerDDLoad(){
require(["dojo/on", "dijit", "dojo/ready"], function(on, dijit, ready){
ready(function(){
var dropDown = dijit.byId("searchAgency");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchLocation");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchCounty");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchRep");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchSenate");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchStatus");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
dropDown = dijit.byId("searchAE");
on.once(dropDown, "onfocus", function() {
loadDropDown(dropDown);
});
});
});
}
registerDDLoad();
The dojo event class, dojo/on expects events to be specified without the 'on':
onFocus = focus
onClick = click
onMouseOut = mouseout
...
I think changing that should fix your problem. I've copied your code into test area on jsFiddle, so you can play around with it.
NB: Since you are re-using the dropdown variable, it will always equal the last filteringSelect (id=searchAE) and never the earlier ones.