If I remove background-green class binding or value binding from the select element then it works as a normal dropdown. But let's say I didn't remove the background-green class binding then after selecting, the selected option is not displayed but if I select again the same selected option or other option then it would be displayed. Same behavior with value binding. So why it's working second time? This is my real concern/confusion.
Here is the link of running example with sample code.
The problem is a mixture of :value="defaultValue" not actually changing (because defaultValue never changes) and also a side effect of a rerender happening the first time.
Since :value is essentially always "", any time the <select> is re-rendered, Vue sets the value to that empty string.
You have handleInput set fillBg = true which triggers a re-render, because background-green was not in the initial render. This means Vue will reset the value of the <select> back to defaultValue (blank)
During the time it appears to work after the first selection, what's actually happening is DOM local state showing what you selected. Since there is no change to the vdom (background-green is already there), Vue is not re-rendering and thus not resetting the value.
The proper way to fix this is to either update defaultValue (perhaps rename this) during the input event or use v-model. The point is to have Vue set the proper value any time it renders.
handleInput(e) {
this.fillBg = true;
this.defaultValue = e.target.value;
},
Related
I have one parent component and child component. I pass value to child component from parent component using #Input(). Now when value will changed from parent , child component will get changed value.
My question is when Input() changed , How to animation those value.
parent-component
<div>
<child [totalPrice] = "price" />
</div>
child-component
<div>
{{ totalPrice }}
</div>
Now, Value in {{ totalPrice }} is changed from parent, and for each changed I wants to animate over screen for indication that something has changed from previous state. How can I do this in angular?
EDIT
Demo on this Stackblitz LInk
above I applied angular animation :enter and :leave. But it works only first time when we selects check-box first time. Second time when value changes, animation is not working.
Fiddled a bit with your stackblitz:
https://stackblitz.com/edit/angular-ivy-2atj3s?file=src%2Fapp%2Ftotal-price%2Ftotal-price.component.html
I have a control boolean that I set on value change (the Input will only fire on distinct changes). I reset it with a slight timeout upon fade in done (#myTrigger.done with stateFrom : stateTo check). Still rough, but generally works.
(If you want something like a checkbox as the input, you should probably make them exclusive.)
I have a good history playing with react. But today I faced a very strange issue.
I have a hamburger which receives a list of values and the one of the values is selected which I send from the parent through this.refs.child1.setValues(). this setValues function calls setState and that one value is selected through className parameter in react.
So in the first step I select first value among 20 values.
the react tab shows this about the first li element:
className="{something} +class1"
rest all elements have:
className="{something}"
which is fine. ('class1' is the class which is added dynamically on setstate) and the dom shows first value selected and the rest unselected.
now problem is in the second step as I select another value say 3rd one, so first value should get deselected and 3rd should be selected and the expected react values for 3rd should be
className="{something} + class1" and for the rest its showing className="{something}"
which is working fine in the react tab BUT in the elements tab both the li elements are getting selected as they both have class1 but class1 should be only with the 3rd element not with the first one (which was previously selected)
Since React works by using the Virtual DOM, it only makes changes in the DOM to elements it detects a change to. So, since you're never actually removing a class from the first element, it never does a rerender of it, it only rerenders the third one because that's the only one you actually changed.
You need to do something like this:
removeClass() {
let allLinks = document.querySelectorAll('.something');
allLinks.map((link) => link.classList.remove('class1'));
//and here just call the function to add the class to the right
//element.
}
All the examples I have found that keep local state can't provide an initial value for the input. In my case a parent component retrieves field from a server and passes these to my input form where the fields shall be editable. But I don't want to pass each change back up the hierarchy if I can avoid it, rather only when the form is submitted (either via button or by pressing enter)
Update: the usage is as follows. Imagine a todo list. The top level holds the list and the detail component. When I click at the list the detail should update to show the selected todo text. That text should be editable.
So as far the the detail component goes the initial state of the input is the text from the list that gets passed down in props. It needs to change when a different todo in the list is selected. On the other hand I should be able to edit it and when submit triggered that todo text should be passed back up via a callback prop.
So I have to keep local state to collect the input, but I want that state to be initialized with the existing todo text from the list. If I use the Facebook example of an uncontrolled form, I find the edited text remains displayed when I switch to a different todo in the list. Maybe I'm doing it wrong or is it a conceptual problem? Using controlled input initializing the state in the constructor doesn't work either because the constructor only gets called once (not on each re-render)!
I solved the problem by using the lifecycle method componentWillReceiveProps(nextprops) where I can set the state to the new props. This method gets called each time a re-render becomes necessary - in my case because the parent changes the childs props.
See https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops
You can set the initial state based on the property passed in from the parent, then edit that state in the component before submitting with the form submission
This is a bit of an odd issue I came across today. I have an application that is using Breeze and Knockout. On one of my pages I allow the user to edit and save project data. The save button is only enabled if a change has been made. To track changes I subscribe to the propertyChanged event. This page has quite a few dropdowns which are causing some problems. Here is an example of one of the dropdowns.
<div>
<label for="projQAManager">QA Manager</label>
<select id="projQAManager" data-bind="options: QAManagers,
optionsText: 'FullName',
optionsValue: 'USERNAME',
optionsCaption: 'None',
value: project().QAManager"></select>
</div>
The issue occurs when project().QAManager is "". The propertyChanged event gets fired as soon as the project is loaded and it shows the QAManager field being changed from "" to null. This is causing the entity to believe it has been modified even though nothing has really changed. If QAManager is already null everything works fine. I suppose I could go through and try and clean the DB and clear out any fields with "" and set them to null if I had to but I would rather not if it can be avoided.
The problem lies indeed with the fact that KnockoutJS assigns the value undefined to the caption of the list box, which you labelled "None".
What happens is that right after the listbox is populated, KnockoutJS checks if your selected value (project().QAManager) matches any of the options listed in the list box. If it does not match, it selects the option with the caption, and as such, the selected value of the listbox is modified, which triggers project().QAManager to get the undefined value.
Excerpt from the documentation of the options binding handler (emphasis is mine):
KO will prefix the list of items with one that displays the text
[caption text] and has the value undefined. So, if myChosenValue
holds the value undefined (which observables do by default), then the
dummy option will be selected. If the optionsCaption parameter is an
observable, then the text of the initial item will update as the
observable’s value changes.
I thought of the following workarounds ranging from the easiest to the hardest, but most "proper":
One of the workaround would be to add to your list of options (QAManagers) an entry which has the value undefined, before it is available as an observable array.
Write a custom binding handler for options that allows to set a given value to the caption item, instead of it being set to undefined. This should consist in copy/pasting 99% of KnockoutJS's implementation of "options", and just changing the code I wrote at option 3.
Change KnockoutJS's source so that a new "optionsCaptionValue" binding is taken into account, like this (I've modified the original code like you should do):
if (allBindings['optionsCaption']) {
var option = document.createElement("option");
ko.utils.setHtml(option, allBindings['optionsCaption']);
var captionsValue;
if (allBindings['optionsCaptionValue']) {
captionsValue = ko.utils.unwrapObservable(allBindings['optionsCaptionValue']);
}
ko.selectExtensions.writeValue(option, captionsValue ? captionsValue : undefined);
element.appendChild(option);
}
I have a dropdown field and its value is pre-selected as soon as its rendered (Say, its a Country field in a signup form). And I have other dropdowns or other components which change the selected value of the first dropdown dynamically. Now I want to fire a method with every "value getting selected" in the dropdown. Is it possible?
To put my question in much more clearer way, I want to create a onDefaultValueSet event and subscribe the first dropdown to it. So in which ever way the dropdown gets any value selected, the corresponding handler (my function) gets called.
I tried to do it with YUI Custom Events, but I am not sure how the browser will be calling(understanding) my handler every time a value is selected in the dropdown.
onSelect (from Default DOM) is not a right answer I guess, as I tried it.
Please help me in tackling this problem.
I am not sure whether this is an answer, but I've found a workaround. Please validate this.
So I was making a item "selected" using javascript-dom manipulation. Meaning, using
domElement.options[5].selected = True;
So with the (YUI)custom event I created, I started calling "fire()" right after this. So the code becomes:
domElement.options[5].selected = True;
onDefaultValueSetEvent.fire(domElement.name);
But I am not sure, what if the particular option is selected in a gui fashion. Meaning, how automatically fire() method is called