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.)
Related
I have a parent component that holds a string as a state. This string is composed with help from other child components.
Then the parent sends this string to a DisplayText component that displays it. However in the DisplayText component there is an internal state for that string and thus the user can change it however they like, and the result
const [myString, setMyString] = React.useState<string>('');
React.useEffect(() => {
// do some stuff with the string and save it
setMyString(string);
}, [...]);
<Textarea
value={myString}
onChange={(value) => setMyString(value)}
/>
(This is just basic React.) I would like to add a button in the parent component that forces the child to override any changes the user has made, and re-render the text coming from the parent. This happens naturally when the state in the parent changes, but how can you simulate the same effect when a button in the parent is clicked?
I could solve this by moving the internal state of editing the text from the child to the parent, so clicking the button can control that, but is there another way without doing so? Because the edited text shouldn't concern the parent. The second solution I thought of would be to force a re-render of the parent but the ways to do so are hacky (changing a dummy state).
Is there a simple solution to this?
Composing a string in multiple child components seems like a bad approach to me. But if you really need or want to do it that way, then adding a button in the partent component, that overwrites myString, should work. The props that refer to this value will update automatically. Just remove the internal state of the children, to have a 'single source of truth'.
That sounds like bad practice to me.
You should:
lift state up to parent and have a default value which is saved. Clicking the button should just reset to the default value.
If you need to change the parent state from one or more childs, you should pass down a setter function which sets the state in the parent.
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;
},
I have a component, which has 4 instances.
User clicks number 2, product B gets selected.
When the dom is re-ordered, later after he selects another option, these 4 instances of the component card-brick are re-ordered (because price changes, so this happens automatically in the flow) all good... except for the fact that the selected element, which was number 2 , moved to position 1.
and... the 2nd element continues to be selected instead of product B!
The ui shows selected product D.
it seems that somehow polymer 2 is ignoring this selected attribute when repainting the DOM. how can I avoid this?
<iron-selector id="something-semantic" attr-for-selected="value" selected={{value}}>
<template is="dom-repeat" items="[[filteredProductosCategorias]]" as="productoCategoria" id="productoTipo">
<div class="card-brick" value="[[productCategoria.id]]" tabindex="1" on-keyup="_seleccionaCategoria">
</div>
</template>
</iron-selector>
the selection is stick to previously selected element in the DOM order. how can I make this selected value to also update don dom changes??
any suggestion to overcome this problem?? users can be confused.
The problem is that dom-repeat doesn't rebuild the elements inside, because that would be a heavy operation. It just assigns new values to child elements, meaning that iron-selector has no clue that the content has changed. In the example, you selected the second element, and after the re-sort, it's still the second element selected.
I'm confused in what _selectCategory does, because if it sets the category, then you probably don't even need iron-selector. I never used that element myself (and would never use it, because it's simple to write it myself). Anyway, if you re-sort using _selectCategory, then just set the new value property with this.set().
I have two DIVs - one, that is always visible, and another one, that gets displayed after I click a button (it is toggable):
<div>
<div>
<small>ADDRESS</small>
<p [appQueryHighlight]="query">{{ address}}</p>
</div>
</div>
<div *ngIf="showDetails">
<div>
<small>NAME</small>
<p [appQueryHighlight]="query">{{ name}}</p>
</div>
</div>
My custom directive works well on the first DIV (it changes the color of letters inside the paragraph that match the query entered in an "input"), but does not work on the second DIV.
Here is an example of how "Test address" looks like when query is "addr":
Test addresswhere bold text is for example red-colored text.
But when I have name John, and query is "Joh", it should also be colored once shown with the button, but it is not.
As I understand, I need to re-run the directive after I click and toggle the second div. Also, probably I have to do this with delay, so it has time to be shown. How can I do this?
UPDATE
Problem with my directive is related to *ngFor - both DIV are located withing ngFor. I have to call directive ngOnChanges or ngOnInit only after the new list get propagated based on the query. I have no idea how to do this, and currently, directives get loaded before ngFor fully loads - this cause problems.
Here is my previous answer:
I finally managed to solve this problem, thanks to #iHazCode.
So firstly, this is probably a duplication of problem described here: Angular 4 call directive method from component
Because my directive hightlights the specific letters in paragraph based on input query, each time the query changes, the directive should fire, thus I am using ngOnChanges withing the directive.
This is not working with *ngIf, because when ngOnChanges fires, the second div and paragraph is not visible.
As a workaround, we can access the directive from out component using #ViewChildren:
#ViewChildren(QueryHighlightDirective) dirs;
And then call it's ngOnChanges method, once div is toggled. In my case, the problem was related with last occurence of the directive within the component:
toggleDetails() {
...
this.dirs.last.ngOnChanges();
}
That was exactly what I was looking for, I hope it will help someone.
In my case I also encountered another problem - the defined DIVs are within *ngFor, which is also propagated based on the query, so I have to make sure that the list will get propagated before calling ngOnChanges. I haven't find a solution for this yet.
ngIf does not show/hide elements. ngIf determines if the element exists on the DOM. You can verify this by looking at the source of your rendered page. Change the code to use ngHide/Show instead.
Hi I want to hide an adf component automatically.I have a selectOneChoice that contain some number (from 1 to 12).
Example when I select 2, it show's two field automatically without clicking any button..
i used this function to hide a declared componenet but just when i click a button..
function enableField(actionEvent) {
var nameInputText = actionEvent.getSource().findComponent("soc1");
nameInputText.setProperty("visible", true);
actionEvent.cancel();
}
i set the componement "soc1" visible = true than through the javascript function i change it..
SO the probleme here is how to read the number from the selectonechoise and how to set the component visible directly without clicking any button.
Actually Rendered won't do what you want. You want to use Visible property instead. Rendered causes the actual markup for the component not to be rendered on the page, so a Partial Refresh will not cause it to appear. Rendered is reserved, usually, to hide items that are secure. We set rendered property to false on the item(s), but then refresh the parent containing component - usually a layout manager - then it works. So either refresh the layout manager that contains the item or use Visible. I demonstrated this exact use case last week in class and it works as described.
Basicaly, you don't need javascript solution or any programming to achieve this.
You should set attributes rendered(this way component won't be rendered at the page at all) and partialTriggers that points to selectOneChoice component for components you want to show or hide. Also you have to set autoSubmit="true" for your selectOneChoice component.
<af:selectOneChoice id="soc1" autoSubmit="true" .../>
<af:panelGroupLayout id="plg1" partialTriggers="soc1">
<af:outputText id="ot1" rendered="#{bindings.lov.inputValue le 1}" inputValue="text1"/>
</af:panelGroupLayout>
Note: its not working code, just a sample
It will work following way, on valueChange event at selectOneChoice component value is submitted and partialRefresh fires for components that have it in partialTriggers specified. And rendered attribute will either render or remove component depending on it's EL expression. Components that should be managed wrapped into another component to make sure PPR reach it when they ain't rendered.