AMP autocomplete how get id from autocomplete results and display only text in input - autocomplete

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"
>

Related

meteor - how to code a bootstrap modal template to re-render html input values even if the user has typed in them

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');
}
}
});
};

Angular2 form: text input populates with "false"?

I have a form to edit instances of a model (modelName). The model has a description field which is a string. The form is set up like this:
<label class="form-group">
<span class="control-label col-md-3">Description</span>
<span class="col-md-9">
<input class="form-control" type="text" name="description" [(ngModel)]="modelName.description" required />
</span>
</label>
And when the edit form is opened using an instance of the model that has a defined description, the form populates with "false" instead of the description. If I add
{{modelName.description}}
to the label attached to the description input, it prints the string as expected.
I would like the form input to populate with the description string instead of "false"?

Real time update between 2 components?

Is it possible to have a realtime update of input fields between two components?
In a component I have an input field which has a v-model="value". I wanna pass that input realtime to the other component and fill it into that input field.
Data of inputValue should be passed to the component 2 as value props. Or maybe I'm wrong with my result?
COMPONENT 1
<template>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="global-{{element}}" v-model="inputValue">
<label class="mdl-textfield__label" for="global-{{element}}">{{ label }}</label>
</div>
</template>
COMPONENT 2
<template>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input name="items[{{prop1}}][{{element}}]" value="{{value}}" class="mdl-textfield__input"
type="text" id="{{element}}">
<label class="mdl-textfield__label" for="{{element}}">{{ label }}</label>
</div>
</template>
<script>
export default{
props: ['prop1', 'element', 'value', 'label']
}
</script>
I tried with ...
this.$dispatch('tag-update', this.inputValue);
... but I need an #keyup.xx. But that's not what I want. I want it to update as soon as I pressed and released a letter, number etc.
You can certainly achieve this with events, or you can move the inputValue up to the parent component or root and pass it to each component as a synced prop.
http://jsfiddle.net/gtmmeak9/118/
The second component doesn't have to be synced if you just want one way binding on it.

Why does reset() function does not work properly with jsviews

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.

About the $dirty property and getting only modified fields in a form

I have a form with few fields and I'm trying to get modified fields only.
Here is what I got so far (simplified version) :
<form name="formTicket">
<div class="item title">
<label for="category-assignation"><?php echo T::_("Assignation :")?></label>
<textarea type="text" name="assignation" cols="50" rows="4" id="category-assignation" data-ng-model="ticket.assignation"></textarea>
</div>
<div class="item title">
<input id="save" type="submit" value="Save" data-ng-click="saveTicketInfo()" />
</div>
</form>
In my controller.js, I have :
$scope.saveTicketInfo = function() {
console.info($scope.ticket);
console.info($scope.formTicket);
//Query to my service to save the data
Category.saveInfo.query({data: $scope.ticket});
};
Prior to AngularJs, I would save my fields in an array at the loading of my form and compare their values with the new values posted. I could still do this but I'm looking for an AngularJs approach.
I've been trying to use the $dirty property of each field and only send to my services those with "true" value but this behavior is not suitable for me : if the defaut value for my field is "test" and the user modify the input to "test2" and modify it back to "test" and post it, $dirty will be true (even if the value has not really changed).
Is there any convenient and optimal way to achieve what I want ?
Thank you for your time.