How can I add Apply, Cancel, and Clear buttons to the date range picker? - ngx-bootstrap

I'm using the ngx-bootstrap date range picker (https://valor-software.com/ngx-bootstrap/#/components/datepicker?tab=overview). I noticed that this picker (which displays two side-by-side calendars) seems to share the template with the single-calendar date picker: https://github.com/valor-software/ngx-bootstrap/blob/development/src/datepicker/themes/bs/bs-datepicker-view.html.
However, despite the presence of Clear, Apply, and Cancel buttons in the template, there seems to be no way to add them to the date range picker via the usual bsConfig method (when I tried, the options are ignored). This may have been a choice on the part of the developers, but whatever the reason, I want to add those buttons.
Is there any way to extend the date range picker in my Angular component to hook into those template elements?
Example...here is the section of the template that contains the apply and clear buttons:
<div class="bs-datepicker-buttons" *ngIf="false">
<button class="btn btn-success" type="button">Apply</button>
<button class="btn btn-default" type="button">Cancel</button>
</div>
There is an ngIf condition, but it's hardcoded to false. How might I override that to make these buttons appear? And, once they appear, how do I add click handlers, since they are omitted in the template?
Thanks for pointing me in the right direction. I've only been coding with Angular (v. 15) for two months, so things like this are still difficult for me to conceptualize.

Related

Vuejs #click event works wrong from time to time

Recenty, I noticed that the checkboxes that I wrote a click event worked incorrectly from time to time. Not everytime but sometimes their #click event works in reverse. Here is what I am trying to tell;
<label class="form-switch">
<input type="checkbox" #click="showElement = !showElement"/>
</label>
I have a simple form switch and there are some css on it which I didn't put here, it looks like a toggle switch. It toggles a data which is showElement. The default state of the data is false and when you click on the toggle it becomes true and false respectively.
<div v-show="showElement>
some content here
</div>
When the showElement is true I want to display the above div, and when it becomes false, I want it to be hidden. There is no problem with that. But here is my question;
If my observation is corret, usually when the project is started for the first time, in other words, when I type npm run serve and start the project, I immadiately go and check if it is working fine or not so I click on the checkbox very quickly over and over andsometimes the click event breaks down and starts working backwards. I mean, when the switch is off, the content is visible, when it is false, the div is showing, but it should be reversed. This happens sometimes when I browse the other pages of the project and return to this component. Is this a bug? Or am I doing something wrong? In the first version of the code it was like below;
<label class="form-switch" #click="showElement = !showElement>
<input type="checkbox"/>
</label>
I accidentally typed the click event to the label element instead of input. I thought that might be the problem. I am still thinking that is the problem but the bug that I explained above still happens sometimes. Do you know why? Can anyone explain?
Usually i find that with checkboxes in VueJS #Click is not the way to go. Try to use #Change event instead. This should make it more consistent.
The reason behind this is that the click event triggers before the value has been updated. Therefore creating the risk of it overwriting the old value instead of the newly updated one
EDIT:
I actually think in this case you might even be able to get around this by simply adding a v-model to the checkbox like so:
v-model="showElement" instead of having either #click or #change.
Verison 1:
<label class="form-switch">
<input type="checkbox" #change="showElement = !showElement"/>
</label>
Version 2:
<label class="form-switch">
<input type="checkbox" v-model="showElement"/>
</label>
Check this fiddle: https://jsfiddle.net/x4wykp2u/4/
Hope this makes sense

ng-bootstrap typeahead determine selection

I've got a typeahead element in my Angular 5 application. What I can't figure out is how to determine the selection. I have this for my resultTemplate:
<ng-template #listSelectionFormatter let-r="result">
<span (click)="onWorkerSelected(r)">{{r.wwid}} - {{r.fullName}}</span>
</ng-template>
So if I click on one of the selected items my callback happens and I can store the result. But if they hit the tab key instead, I don't know how to grab the selection.
I basically need to be able to call propagateChange as this is used in a ControlValueAccessor.

How can I change the styleClass of a control while also doing a partial refresh on another component?

I have a straightforward XPage that lets a user answer a question with a simple Yes/No/NA response using radio buttons. I have restyled the radio buttons to look like a bootstrap button group to make it visually more interesting for the user. If the user chooses "Fail" then they are informed that they need to do something else - easily done with a simple partial refresh to a div further down the page.
This all works fine.
The problem I'm having is that I'd like it so that when the user selects an option, I would like to add a new class of "active" to the selected option so that it highlights in a pretty colour. But for the life of me I can't get this to work and though I'm sure it's a straight forward problem, I can no longer see the wood for the trees.
My current (abridged) iteration of the radio button code is this:
<xp:div styleClass="btn-group item-result" id="edit-result" loaded="${Question.open}">
<xp:radio text="${lbl.kwPass1}" id="itemPass"
styleClass="btn btn-pass #{(item.itemResult eq '0')?'active':''}" groupName="itemResult"
selectedValue="1">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="actionAlert">
<xp:this.script><![CDATA[XSP.partialRefreshPost('#{id:edit-result}');]]></xp:this.script>
</xp:eventHandler>
</xp:radio>
<!-- other radio buttons -->
</xp:div>
<!-- other page compenents -->
<xp:panel id="actionAlert">
<!-- panel content and appropriate rendered value -->
</xp:panel>
This was attempting to do a chained partial refresh on the radio button container so that the EL would evaluate and apply/remove the 'active' style based on the document datasource ('item') value. I have also tried using dojo.addClass, dojo.removeClass, XSP.partialRefreshGet and other options. I don't mind what the solution is as long as it's efficient and works. I'd prefer not to move the actionAlert panel to within the same container as the radio buttons and I can't do a full page refresh because there are other fields which will lose their values.
Some notes:
I'm not using a RadioGroup control because it outputs a table and I haven't got around to writing my own renderer for it yet. Single Radio button controls work fine for what I need them to do.
I originally tried using the full Bootstrap solution of using "data-toggle='buttons'" (source) which sorts out applying the "active" style fine but then, inevitably, prevents the partial refresh from working.
the radio button styles are clearly not Bootstrap standard
Any assistance pointers or, preferably, working solutions would be appreciated.
You need to aim your partial refresh at the div containing all your radio buttons. Give it an id, so you can address it.
Partial refresh, as the name implies, refreshes one element and its content only. So you target the element that covers all of the items you need to recompute.
Stepping away from the problem, a couple of beers and an episode of iZombie later, I realized what I was doing wrong and sorted it out. So, for posterity, here is the simple solution that I swear I tried earlier but clearly works now:
<xp:div styleClass="btn-group item-result" id="edit-result" loaded="${Question.open}">
<xp:radio text="${lbl.kwPass1}" id="itemPass" value="#{item.ItemResult}"
styleClass="btn btn-pass" groupName="itemResult" selectedValue="1">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="actionAlert">
<xp:this.script><![CDATA[dojo.query('.item-result > .btn').removeClass('active');
dojo.query('.btn-pass').addClass('active');]]></xp:this.script>
</xp:eventHandler>
</xp:radio>
<!-- et cetera -->
The many places I was going wrong:
In my code in the question, I was calling XSP.partialRefreshPost in the CSJS script of the radio button when it should have been in the onComplete of the eventHandler. It has to be chained to another partial refresh so that it runs after it, not at the same time. I did end up getting this right - but overlooked something I'll come to in point 3.
In my original attempt to use Dojo, my first mistake was to try and target the ID of the radio button, something like:
dojo.addClass(dojo.byId('#{id:radio2}'),'active');
This actually works as expected, so long as you remember that the ID of the radio button on the XPage refers to the actual radio button control and not the label wrapping; and the label is what I wanted to style. So the class "active" was being actually being added, just not to the element I thought it was. I should have spotted this in my browser code inspector except for the third thing I got wrong:
Ironically, I sorted out the first issue, remembering to put the XSP.partialRefreshPost into the onComplete - and then didn't remove it when trying to run the Dojo.addClass(). So I didn't notice the mistake with the addClass targeting the wrong element because after it ran, the partial refresh updated the container and removed the class I had just added which made me think that nothing was working.
So now I have some neatly styled radio buttons that don't look like radio buttons and it's all managed client side without any unnecessary partial refresh trips to the server barring the one where I actually need to look stuff up from the server. And the vital lesson is - sometimes you just need to step away from a problem and come back to it with fresh eyes later on.

Bootstrap Popover Link Inside a Label

On a form, I have a typical opt-in text checkbox but also have a link in that label. That link doesn't go anywhere but rather triggers a Bootstrap 3 Popover for additional detail.
It works, however clicking the popover link also unchecks the checkmark. Saw other questions on SO and solutions but they were for normal links and didn't apply to a javascript link link like this. Any thoughts?
The of course first thing one would think of is to have the link outside the label, but then the text won't wrap with the preceding text and will always have to appear beneath the disclaimer text which is not desired.
<div class="checkbox">
<label>
<input class="optin" type="checkbox" checked value="">My disclaimer text here. <a type="button" data-toggle="popover" title="Popover Title Here" data-content="Popover body text here">My Link</a>.
</label>
</div>
Assuming I need to integrate stop propagation somehow but can't seem to determine how to integrate in this scenario.

disabling a submit button till validation

Is there a way using dojo/dijit to disable the submit button till all the fields in a form are valid. Kind of like having a dojo > method > onChange inside the form? So the submit button only becomes enabled when all the form elements have meet their criteria?
Are you using a dijit.form.Form widget as your form? If you are, I would suggest connecting to the Form's onValidStateChange event. The docs for this event specifically state your use case:
onValidStateChange
Defined by dijit.form._FormMixin
Stub function to connect to if you want to do something (like disable/enable a submit button) when the valid state changes on the form as a whole. Deprecated. Will be removed in 2.0. Use watch("state", ...) instead.
The best way to see what events are available for a given widget is to look at the API Documentation for the widget you are interested in under the "Event Summary" heading. The dojocampus reference documentation often leaves out examples for references to some of the more obscure features of the widgets.
I would suggest to have a hidden button which will submit the form. When you click visbile button run a javascript function that validates all the input and then clicks on the hidden button to submit the form. Please find the pseudo code below
<form action="register">
<input dojoType="dijit.validation.TextBox"/>
<button onClick="validateall()">submit</button>
<button id="submitForm" type="submit" hidden="true"/>
</form>
function validateAll(){
if(AllOk){
clearErrorMessage();
dojo.byId('submitForm').click();
}else{
showErrorMessage();
}