I'm fairly new to Ember and I'm trying to implement a Collapse method when I have clicked on a checkbox as a part of my form. This checkbox is inside a collapsed section part of a button group I have in my form.
Template.hbs
{{#bs-button onClick=(action "toggle")}}
{{#if collapsed}}
{{form.element controlType="checkbox" label="View Additional Fields" property="additionalFields"}}
{{/if}}
<div>
{{#bs-collapse collapsed=collapsed}}
{{form.element controlType="checkbox" label="Property" property="property"}}
{{form.element controlType="textarea" label="Instructions:" name="instructions" property="instructions"}}
{{/bs-collapse}}
</div>
{{/bs-button}}
Component.js
collapsed: true,
actions: {
toggle() {
let toggleValue = !get(this, 'collapsed');
set(this, 'collapsed', toggleValue);
}
}
When running ember serve and I go to my form if I click on the checkbox an error pops up in Ember Inspector:
Assertion Failed: You cannot use the form element's default onChange action for form elements if not using a model or setting the value directly on a form element.
You must add your own onChange action to the form element in this case!
Error
If I change onClick to onChange then fields aren't displayed when I click the checkbox, but I still get the error. What would be the best way to go about trying to fix this problem?
The error you are facing has nothing to do with {{bs-collapse}} or your {{bs-button}} onClick action. It seems like your {{bs-form}} does not have a model property but ember-bootstrap requires that one if you don't that an onChange action to each {{form.element}}. You find details in ember-bootstrap api docs and in source code.
Related
So the image above is my code inside a comp.js (Vue component) when the user clicks 'Update' button, it will grab the updated input and push it to firestore.
I put v-on:emit on every single input and I tried to reference it on the 'Update' button.
This is my modal inside the HTML file, I tried to connect the function from comp.js to function.js.
However, the methods above didn't work and it gave me the error below.
I'm not really sure how to grab the value from each input and connect
UPDATED CODE BASED ON ITTUS'S SUGGESTION:
So based on the Ittuss suggestion below, I tried to pass over to items through the emit inside the Update button, I did this because I want to pass all the input values above the button to update the Firestore database.
I changed the cuisedit to this:
And I updated the function in the .js to this:
However, I received an error saying that I didn't reference correctly.
Do you know why it isn't grabbing the value emitted from the button?
In your cuiseedit component, $emit should contain only 1 additional parameter:
<button #click="$emit('some-change', obj2.id)"></button>
and in component:
<transition name="fade">
<cuisedit v-if="showModal" :obj2="cuisinemodal" #some-change="updateData">
</cuisedit>
</transition>
updateData: function (id) {
firestore.collection("koreanbap-cuisines").doc(id).update()....
}
Note
If you want to pass more data, you should wrap them to an object
<button #click="$emit('some-change', {id: obj2.id, event: $event})"></button>
I'm making a little app in meteor to store car inspection registries, it uses an "autoform" form to insert the values that i need then i present those values somewhere else, one of my templates presents all items stored in the collection and i managed to make a "details" button that shows a modal that should have more details.
App screenshot
Modal Screenshot
Currently i have a hidden field with the id from the item in the collection, i send that id with a session and the template with the modal gets that session.
<form>
<button type="submit" class="btn btn-md btn-warning" ><i class="fa fa-list"></i> Detalles</button> //submit button
<input type="hidden" name="idp" value={{_id}} size="1"> //Hidden field with item id
</form>
It's working just fine, the problem is that i need the other buttons in the panel to act differently, yet all of them need the id from the item in the collection. The only way i know how to catch the contents from an element in a template is through event.target."elementName".value and this only works with the submit event i think, i tried document.getElementById with the click event but that only showed the first item in the collection, even if i clicked on the "details" button of another item.
The event code:
Template.Inspeccion.events({
'submit form'(events){
event.preventDefault();
var id= event.target.idp.value;
Session.set('id-carro', id);
Modal.show('Detalles');
},
The modal code:
Template.Detalles.helpers({
carro: ()=> {
var id= Session.get('id-carro');
return Inspeccion.findOne({_id:id});
},
});
Is there anyway to listen to different submit buttons or is there any other way to extract the contents from the template and use a different event that will work per button?
I'm pretty sure i'm missing something obvious but i can't find a solution online.
Thanks in advance and Happy Holidays.
You can define click events on buttons and refer to the current data context with this in your javascript. Ex:
html:
<button id="foo">click me</button>
js:
Template.Inspeccion.events({
'click #foo'(){
console.log(this._id); // "this" will be the data context that was clicked on
}
});
In this AngularJS controller for a pre-filled form, fetching the data is triggered by an event using $broadcast and $on. However, when the data updates, only some of the corresponding fields get updated in the view.
$scope.currentHouse = {};
$scope.$on('houseInfoLoad', function(event, data) {
$scope.currentHouse = data.houseDetail; //does not refresh the view
console.log($scope.currentHouse); //output is correct
//the next three calls refresh the corresponding fields in the view
$scope.changeGarageRadioValue($scope.currentHouse.hasGarage);
utils.setSelection($scope.houseKeywords, $scope.currentHouse.keyword.id);
utils.setSelection($scope.houseTypes, $scope.currentHouse.type.id);
});
changeGarageRadioValue() essentially does what it says, and utils.setSelection(list, id) adds a selected = true property to the element of the list that has the id. This has the effect of setting the value of a select field (using isteven's multi-select plugin).
The view has a few text fields bound to properties of $scope.currentHouse, as well as these radio buttons and select fields.
The result is that the text fields sometimes do not get updated, however the select and radio buttons do.
Here's what I tried unsuccessfully:
Wrapping everything in a $timeout();
Calling $scope.$apply() after setting $scope.currentHouse (throws an error saying that we are already inside an $apply())
Changing the initial definition of $scope.currentHouse from {} to an object with each of the fields set to null.
Can anyone see what I am missing, or how to force trigger the refresh?
EDIT : with extracts from the view :
A text field:
<label>ADDITIONAL DESCRIPTION</label>
<div>
<input type="text" ng-model="currentHouse.additionalDescription" class="input-mandatory" value=""/>
</div>
A multi-select:
<label>TYPE</label>
<div>
<div directive-id="houseType" multi-select input-model="houseTypes" output-model="currentHouse.type" button-label="text" item-label="text" selection-mode="single" default-label="Select" tick-property="selected" ></div>
</div>
The radio buttons :
<div><label>HAS GARAGE</label></div>
<div>
<div id="radiobuttonNo" ng-click="changeGarageRadioValue(false);">
NO
</div>
<div id="radiobuttonYes" ng-click="changeGarageRadioValue(true);" class="active">
YES
</div>
</div>
EDIT #2 as per Alok Singh's suggestion:
I tried putting data.houseDetail into $scope.currentHouse.house instead of $scope.currentHouse directly, and changing the view accordingly. Still no results.
$scope.currentHouse = data.houseDetail
You cannot get the updated value of currentHouse because its a model.
So change the above code i.e
$scope.currentHouse.house = data.houseDetail
In my view model I have a field. This field can be selected from a drop down list or entered in a textbox. I have two radio buttons which allows to select between drop and textbox.
<div class="frm_row" id="contractorRow">
#Html.RadioButton("IsContractorNew", "false", true)
#Html.Label(#Resources.SomeLabels.Existing)
#Html.RadioButton("IsContractorNew", "true", false)
#Html.Label(#Resources.SomeLabels.New)
<div class="frm_row_input" id="contractorDropDownList">
#Html.DropDownListFor(model => model.CONTRACTOR, Model.Contractors)
#Html.ValidationMessageFor(model => model.CONTRACTOR)
</div>
<div class="frm_row_input" id="contractorTextBox" style="display: none;">
#Html.TextBoxFor(model => model.CONTRACTOR)
#Html.ValidationMessageFor(model => model.CONTRACTOR)
</div>
</div>
I prepared a javascript code for hiding, showing and clearing controls while selecting radio buttons. The problem is - field is bound only to the first control (drop down list).
EDIT:
I solved this problem by creating one hidden field and scripting whole logic to bind active control with it and therefore with the model. Anyway if anyone knows simpler solution, please post it.
I know this is an old question, but for those dealing with this issue, here's a solution:
Explanation
When a form is submitted, input elements are bound to the model by their name attribute. Let's say you use HTML helpers to generate your form, and you generate two input fields which bind to the same property on the model. When rendered to the DOM, they both have the same name attribute.
<input name="Passport.BirthPlace" id="birthPlaceDropDown" ... >
<input name="Passport.BirthPlace" id="birthPlaceInfoTextbox" ... >
When the form is submitted, it will bind the first (in the DOM) input it finds to Passport.BirthPlace
A Solution
The quick and easy way to fix this is to use JQuery to change the name of the field you don't want bound on submit. For me, I use a checkbox to toggle which field shows. When the checkbox changes, I hide one control, change its name attribute, and show the other one (and change it's name attribute to Passport.BirthPlace) It looks like this, basically:
First, I run this on document ready
$('#birthPlaceInfoTextbox').attr('name', 'nosubmit'); // Change name to avoid binding on inactive element
Then, I create a listener for my checkbox which toggles which control should be bound:
$('#notBornUSCheckbox').change(function() {
if (this.checked) {
// Not born us was checked, hide state dropdown and show freeform text box
$('#stateDropDownSection').addClass('d-none'); // Hide drop down
$('#birthPlaceDropDown').attr('name', 'nosubmit'); // Change name to something other than Passport.BirthPlace
$('#birthPlaceInfoTextbox').attr('name', 'Passport.BirthPlace'); // Set this one to be bound to the model
$('#stateTextboxSection').removeClass('d-none'); // Show the textbox field
} else { // Opposite of above lines
$('#stateDropDownSection').removeClass('d-none');
$('#stateTextboxSection').addClass('d-none');
$('#birthPlaceInfoTextbox').attr('name', 'nosubmit');
$('#birthPlaceDropDown').attr('name', 'Passport.BirthPlace');
}
});
Instead of using Razor #Html.TextBoxFor... for your textbox, you could try using raw HTML e.g. <input />. Also, have your JavaScript code remove the other field from the DOM entirely when a radio button is clicked, before submitting the form.
I have just started using Knockout.js My form has elements which I call questions. I hide/show them based on user selections. When user hits the submit button I want to post only the visible questions at the time of submit. What I have is this:
// length of Results(questionArray) is 260
var vmToPost = viewModel;
delete vmToPost.__ko_mapping__;
ko.utils.arrayForEach(vmToPost.Results(), function (question) {
if (!(vmToPost.getQuestion(question.QuestionID()).visible())) {
ko.utils.arrayRemoveItem(vmToPost.Results(), question);
}
});
The util function arrayForEach is behaving strange. It loops through the array very differntly. I had to hit the submit button 7 times to get all the visible elements and come out of the util function. It doesnt throw any error message in the console or the fiddler.
What am I doing wrong. Please help.
Html contains a built-in way to skip items from being submitted. It's the disabled attribute, which can be controlled using Knockout with the enable or disable bindings.
<div data-bind="visible: visible">
<label>Name: <input name="name" data-bind="enable: visible"></label>
</div>