I have a radio button defined as:
<.label(
....styling
^.onClick ==> { event =>
event.stopPropagation()
props.select
},
<.input.radio(
....styling
^.onChange ==> { event =>
event.preventDefault()
Callback.empty
},
^.checked := props.isActive,
^.disabled := props.disabled
)
)
So basically I aim to invoke a callback(props.select) on click of the radio button, and stop further propagation(hence event.stopPropagation). Also, on change event I want default operation not to happen(hence event.preventDefault).
But I observe that callback(props.select) is invoked 2 times when radiobutton is clicked.
What am I missing here?
Two things.
Firstly, because it's a side-effect, you should be wrapping event.preventDefault() in a callback. So either Callback(event.preventDefault()) or you can use the helper method event.preventDefaultCB.
Secondly, React likes to invoke things twice in dev mode, (it's not a scalajs-react thing). There's https://github.com/facebook/react/issues/12856#issuecomment-390206425 and there are a bunch of other examples on SO. Try searching for just React instead of scalajs-react.
Related
I'm using the Enterprise Ag-Grid version in my Angular 6 application. I have a Set Filter in it. I added the 'Apply' button to the filter:
apply: Set to true to include an 'Apply' button with the filter and
not filter automatically as the selection changes.
The question is how can I hide the mini filter menu after button is pressed? I didn't find any documentation about this possibility in the official web site. But I find a comment in the internal library src file, specifying in the IComponent.ts:
/* A hook to perform any necessary operation just after the gui for this component has been renderer
in the screen.
If the filter popup is closed and reopened, this method is called each time the filter is shown.
This is useful for any
logic that requires attachment before executing, such as putting focus on a particular DOM
element. The params has one callback method 'hidePopup', which you can call at any later
point to hide the popup - good if you have an 'Apply' button and you want to hide the popup
after it is pressed. */
afterGuiAttached?(params?: IAfterGuiAttachedParams): void;
At the moment I can not understand how to set afterGuiAttached function to achieve the goal described above.
Could anyone help me?
Thanks in advance!
As you already checked afterGuiAttached is a part of Filter Component
So this function accessible inside custom filter like here.
So all that you should do is define afterGuiAttached inside:
export class PartialMatchFilter implements IFilterAngularComp {
afterGuiAttached(params){
params.hidePopup() <- executing will close the filter
}
}
afterGuiAttached - would be executed on init as described (but Apply button also would be custom and you should handle it by your self). You can bind hidePopup function to your custom filter parameter and use it when it would be necessary.
export class PartialMatchFilter implements IFilterAngularComp {
private hideFilter:Function;
afterGuiAttached(params){
this.hideFilter = params.hidePopup;
}
}
Executing this.hideFilter() will close your filter;
I've made a dummy sample based on the referenced demo
So right now I have a table that displays some values and I have an indicator for conflicts. When the user clicks the indicator a new div appears with some animation to list all the conflicts.
Here is my HTML:
<span data-bind="if: hasConflict, click: $parent.selectProperty" class="conflictWarn"><i style="color: darkorange; cursor:pointer;" class="icon-warning-sign"></i></span>
The data might look something like this:
{
name:Property 1,
id: 1,
hasConflicts: no,
name:Property 2,
id: 2,
hasConflicts: yes,
conflicts: {
name: conflict1,
name: conflict2
}
name:Property 3,
id: 3,
hasConflicts: yes,
conflicts: {
name: conflicta,
name: conflictb
}
So the first table is going to look like this:
Property 1
Property 2 !
Property 3 !
Where ! is a conflict indicator. Clicking on the ! would display the conflicts div and also display conflict1 and conflict2 or conflicta and conflictb depending on which was clicked.
Here is the model we are working with. It's a bit complex because of the mapping for the properties from signalr. the "selectProperty" and "selectedProperty" was our way of saying which one to display conflicts for, but I'm not convinced this is the best way to do it.
function ItemViewModel() {
var self = this;
self.name = ko.observable("");
self.itemType = ko.observable("");
self.propertiesArray = ko.observableArray([]);
self.properties = ko.mapping.fromJS({});
self.selectedPropertyName = ko.observable("");
self.getItem = function (name) {
$.connection.mainHub.server.getItem(name).then(function (item) {
ko.mapping.fromJS(item.properties, self.properties);
self.propertiesArray(item.propertiesArray);
self.itemType(item.itemType.name);
self.name(item.name);
});
self.selectProperty = function (a, b) {
self.selectedPropertyName(a);
};
};
}
Originally the click event directly called a javascript function that did all the animation, but my coworker thought that might violate best practices for separating data and viewmodel in MVVM. Does it? Should we leave it calling the viewmodel function of "selectProperty" which allows us to pass context for the "conflicts popup" div? If so, do I just call the javascript function to do the animation from within the selectProperty function?
p.s. I've edited this about 800 times so I apologize if it's impossible to follow.
update I have the bindings working now, so I really just want to know what is best practice when it comes to UI animations and Knockout. Change the viewmodel from the javascript function or call the javascript function from the viewmodel function?
Regarding UI animations in my opinion it is best practice to implement custom bindings. This way code is encapsulated and it is easy to find where it is used. Check Animated transitions example on knockout website.
i'm going to extends Thomas answer with one point, custom bindings don't work when you want to animate the rendering / unrendering of the 'if' or 'with' bindings. an animation binding that tries to run at the same time as an 'if' or 'with' won't be able to complete the animation before the other binding alters the DOM, possibly removing the elements being animated from the page. there is no way to defer the binding processing until after the event completes.
for these cases animations should be implemented via the 'afterAdd' and 'beforeRemove' callbacks of the 'foreach' binding when the desire is to animate an element being added and removed from the page. 'if' and 'with' bindings can be rewritten as 'foreach' with little effort, as 'foreach' can take a single argument instead of a list. i really wish the animation tutorial would be extended to include this workaround.
I am adding a click event to a checkbox which will show/hide additional fields depending on its checked status. I want the handler to fire on load to set up the initial page structure. For some reason triggerHandler is not working on the field. If I change it to 'trigger' the handler will fire, but the checkbox status will also change. Can you see what i've done wrong/why triggerHandler won't work?
$('body').on("click", "#hdimage", function(){
console.log('hd');
if(!$('#hdimage').is(':checked')){
$('.sd-dim').hide();
} else {
$('.sd-dim').show();
}
});
$('#hdimage').triggerHandler('click');
That happens (as described in the docs) because
Events created with .triggerHandler() do not bubble up the DOM hierarchy; if they are not handled by the target element directly, they do nothing.
and since you use the delegated syntax of the .on() method which lets body handle the click event that occurs on the #hdimage element, that event never reaches the body..
Your Event is not bound to "#hdimage" its bound to 'body'
$(document).ready(function(){
$('#hdimage').on("click", function(){
alert("dostuff")
});
$('#hdimage').triggerHandler('click');
});
I want to attach a event to dynamically created element class.So i used live function but it was not triggered. So checked live function reference ,there i red below notes
As of jQuery 1.7, the .live() method is deprecated. Use .on() to
attach event handlers. Users of older versions of jQuery should use
.delegate() in preference to .live().
so decide to use on function,But it still not working.The text field is already attached with jquery ui datpicker.On another element select i disabled that field.
jQuery("#from").attr('disabled','disabled')
.removeClass('date_picker_bg')
.removeClass('hasDatepicker')
.addClass('date_picker_disabled');
after disabled if i click i want to show alert or tooltip.so i tried this,but not working
jQuery(".date_picker_disabled").on("click", function(event){
alert('hi');
});
What may be the problem
I am using jquery 1.7.1 ( jquery-1.7.1.min.js)
The problem is that jQuery(".date_picker_disabled") finds elements with that class and binds to them. If elements don't have the class at the time the binding is made, the events will not be handled.
The on function allows you to get round this by handling them on another element when the event "bubbles up to" a parent element. In this instance, we could say the body element – there may be a more specific common parent you could choose.
jQuery(document.body).on('click', '.date_picker_disabled', function(event) {
alert('hi');
});
The event handler is now bound to the document.body element. All clicks that happen anywhere in the body are tested to see if they originated from an element matching the selector. If so, the handler is fired.
This is explained on the documentation for the on function. It is the same behaviour as was present in previous versions of jQuery with live and delegate functions.
Having taken another look at your code, you have disabled="disabled" set on your input element. click events are not fired on disabled elements.
This is tricky.
When your code runs, your element does not have .date_picker_disabled class so your jQuery(".date_picker_disabled") returns nothing and .on() is not called.
Apply .on() on the outer element and use the selector parameter:
// you can also do $(document).on()
$(<outer element>).on('click', '.date_picker_disabled', function() {
// do something
});
This will delegate the event to the <outer element>. The handler will only be executed if an element with class .date_picker_disabled has been clicked (second param).
From the documentation of .live():
Rewriting the .live() method in terms of its successors is
straightforward; these are templates for equivalent calls for all
three event attachment methods:
$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+
So in your case, you would do:
$(document).on('click', '.date_picker_disabled', function(event){
alert('hi');
});
I was using jQuery 1.7.2 and tried all proposed methods:
Didn't work:
$(document.body).on('click', '.collapsible-toggle' function() {
console.log('clicked');
});
Didn't work:
$(document).on('click', '.collapsible-toggle' function() {
console.log('clicked');
});
None of them worked until I tried the following:
----- Worked! ----
$('body .collapsible-toggle').on('click', function() {
console.log('clicked');
});
Maybe you should do:
jQuery("body").on("click",".date_picker_disabled", function(event){
alert('hi');
});
in this way you attach the event handler to the bosy and specify to fire that event only when that selector ".date_picker_disabled" is matched.
BTW this is exactly how live() worked
try :
$(document.body).on( "click", ".date_picker_disabled", function() {
alert('hi');
});
document.body helps for dynamic html too.
Just chekc it out: .on not working on dynamic html
how can we implement a multiple event in jeditable, i want to bind two events for a certain div, like dblclick and Enter key
$('.edit').editable('some.php', {
event : "dblclick",
tooltip : "Double click or press Enter Key to edit..."
});
thanks
Well obviously, this is a property managed by the jEditable script, so your only solution would be to dig in jEditable.js and add another possibility for the event property, which would include the events of your liking ;)
GL - I'm about to do just the same right now. - I'll post some info when I'm done.
Ok so it was pretty easy --
Two changes in the jquery.jeditable.mini.js
find and replace :
$(this).bind(settings.event,function(e){if(true===$(this).data('disabled.editable')){return;}
with
var eventlist=settings.event.split(',');$(this).bind(eventlist[0],function(e){if(true===$(this).data('disabled.editable')){return;}
And then, at the end of the bound function -->
find and replace
$(self).attr('title',settings.tooltip);return false;});});
with
for(z=1;z<eventlist.length;z++){
var funcname_of_no_collide_doom=eventlist[0];
$(this).bind(eventlist[z],function(){$(this)[funcname_of_no_collide_doom]();});
}
And tadaam you just need to set the event property using a list of valid jQuery events, like event : 'dblclick,click,blur,tomato'
Actually that mod was funny ... but the real simple solution is offered by jQuery directly :
http://api.jquery.com/bind/
rtfm --