DatePickerAura
DatePickerAura copied to clipboard
Using in VF Page
I have designed an SLDS VF page that uses dynamic fields from a field set to populate. However, the standard datepicker only shows the link, not a calendar. I can't seem to get your datepicker connected correctly. Could you provide more detail on the correct setup? Thanks!
Hi Joshua, can you send me the code for your page, or a reduced version that exhibits the same issue?
On 18 Mar. 2017 18:07, "Joshua Moody" [email protected] wrote:
I have designed an SLDS VF page that uses dynamic fields from a field set to populate. However, the standard datepicker only shows the link, not a calendar. I can't seem to get your datepicker connected correctly. Could you provide more detail on the correct setup? Thanks!
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rapsacnz/DatePicker/issues/5, or mute the thread https://github.com/notifications/unsubscribe-auth/AAnSkPR9Wvn2hZ9IjQwIQTbpsNtkG030ks5rm2Z5gaJpZM4MhTAV .
Hey Caspar, I have made no changes to the code from github, only built the components in my org.
The Object is custom, but our instance is called review. The end goal is getting a slds styled date picker to show for the date fields that are displayed via the apex:repeat. However, in testing with a single input field, I was still not seeing a datepicker, so I believe something is not connected correctly.
Here is what I have for VF and wrapper: VF page: apex:includeLightning/ … <apex:inputField id="actualFinal" showDatePicker="false" value="{!Review.Actual_Final_Signature__c}" /> --showDatePicker is set to false in this illustration, but I have been testing both on and off. The standard lightning date picker does not work on a set of fields shown by apex:repeat as they have multiple types. So date fields come through with the link to set to today’s date, but no calendar to pick the date. …
Wrapper:
<aura:component > <aura:attribute name="review" type="Custom_Review__c" default="{'sobjectType' : 'Custom_Review__c', 'recordType.Name' : 'Special_Review'}, 'Actual_Final_Signature__c' : ''}" /> <aura:handler name="dateChangeEvent" event="c:DateChange" action="{!c.handleDateChange}" /> <aura:attribute name="callback" type="String" description="Call this to communicate results to visualforce page" access="global"/> <c:DatePicker aura:id="actualFinal" label="Actual Final Signature" value="{!v.review.Actual_Final_Signature__c}" formatSpecifier="MM/dd/yyyy" /> </aura:component>
Wrapper Controller: ({ handleDateChange: function(cmp, event, helper) { var func = cmp.get('v.callback'); if (func){ func({fieldName:"Actual_Final_Signature__c",value:event.getParam("value")}); } } })
I did add a closing curly brace in the $Lightning script in the VF page after the field as I got a compilation error from the github implementation code. That seemed the logical place for it since it’s a merge field. From the docs, it seems there needs to be an app listing a dependency with access=”GLOBAL” and extends=”ltng:outapp”. Not sure if that plays a role.
Thanks for your help!
Regards, Joshua
Hi Joshua, can you send me the code for your page, or a reduced version that exhibits the same issue?
On 18 Mar. 2017 18:07, "Joshua" [email protected] wrote:
I have designed an SLDS VF page that uses dynamic fields from a field set to populate. However, the standard datepicker only shows the link, not a calendar. I can't seem to get your datepicker connected correctly. Could you provide more detail on the correct setup? Thanks!
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rapsacnz/DatePicker/issues/5, or mute the thread https://github.com/notifications/unsubscribe-auth/AAnSkPR9Wvn2hZ9IjQwIQTbpsNtkG030ks5rm2Z5gaJpZM4MhTAV .
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/rapsacnz/DatePicker/issues/5#issuecomment-287519127, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AHKJKF55CDYITkBt5_MAkQtzZ-SfeQ9Wks5rm3HvgaJpZM4MhTAV.
In the $Lightning.use
code, you need to refer to a specific id so the javascript knows where to attach the picker to.
So you will need as many $Lightning.use
calls as you have items in the <apex:repeat>
. You could try putting a lightning use call inside the repeat and using the special id syntax to refer to it.
ie:
<apex:page id="myPage">
<apex:variable value="{!1}" var="rowNum"/>
<apex:repeat id="myRepeat">
<apex:inputText value="{!something}" id="inputDate"/>
<script>
$Lightning.use("c:DatePickerApp", function() {
$Lightning.createComponent(
"c:DatePickerWrapper",
{value : {!review.Actual_Final_Signature__c},
callback: function(){
alert('callback');
}
},
"myPage:myRepeat:" + {!rowNum} + "myInput", //<--id is here
function(cmp) {});
});
</script>
<apex:variable var="rowNum" value="{!rowNum + 1}"/>
</apex:repeat>
So the tricky part is building that id, since it is generated dynamically.
In this instance, you would need to build up the string and it would be something like:
"myPage:myRepeat:" + {!rowNum} + "myInput". Since there is no rowNum
in Visualforce, you have to do you own:
Add this above the repeat:
<apex:variable value="{!1}" var="rowNum"/>
Inside the repeat, increment it.
<apex:variable var="rowNum" value="{!rowNum + 1}"/>
(I've already added it above).
Hopefully you can take this example and just use it.
Note, this could quite heavy - one picker for each field. Another option is to use lazy loading and add the picker in an onclick attribute on the code. You may even be able to pass the id in the onclick call, which would save a lot of fussing.
A snippet:
<apex:inputText value="{!something}" id="inputDate" onclick="handleClick(this.id)"/>
<script>
function handleClick(id){
$Lightning.use("c:DatePickerApp", function() {
$Lightning.createComponent(
"c:DatePickerWrapper",
{value : {!review.Actual_Final_Signature__c},
callback: function(){
alert('callback');
}
},
id, //id you passed in above
function(cmp) {});
});
}
Hope this helps!!! (I'm very confident that's not the actual datepicker itself - it's in use in several of my production components)
Thanks, Caspar!
I still can’t get the date picker to instantiate. I just switched the id “lightning” in the Lightning.use call for “actualFinal”, but that still did not bring up the datePicker after a refresh even without it being in a apex:repeat loop. Trying to simplify to see what I’m missing. Great idea on the lazy loading idea…sounds like that could be the ticket for the repeat. I just need to figure out what I missed to get one field to work.
API version is 39.0
Updated vf page:
VF page:
<apex:includeLightning/>
…
<apex:inputField id="actualFinal" value="{!review.Actual_Final_Signature__c}" /> -not in a repeat, for testing. Just a single field on a vf page
<script>
$Lightning.use("c:DatePickerApp", function() {
$Lightning.createComponent(
"c:DatePickerWrapper",
{value : {!review.Actual_Final_Signature__c},
callback: function(){
alert('callback');
}
},
"actualFinal",
function(cmp) {});
});
</script>
Wrapper:
<aura:component >
<aura:attribute name="review"
type="Custom_Review__c"
default="{'sobjectType' : 'Custom_Review__c',
'recordType.Name' : 'Special_Review',
'Actual_Final_Signature__c' : ''}"
/>
<aura:handler name="dateChangeEvent" event="c:DateChange" action="{!c.handleDateChange}" />
<aura:attribute name="callback" type="String" description="Call this to communicate results to visualforce page" access="global"/>
<c:DatePicker aura:id="actualFinal" label="Actual Final Signature" value="{!v.review.Actual_Final_Signature__c}" formatSpecifier="MM/dd/yyyy" />
</aura:component>
Wrapper Controller:
({
handleDateChange: function(cmp, event, helper) {
var func = cmp.get('v.callback');
if (func){
func({fieldName:"Actual_Final_Signature__c",value:event.getParam("value")});
}
}
})
I have no doubt that it is something on my implementation…but I’m new to lightning (and somewhat to js) so this is a learning experience. Unless you see something else specific on this, I think I will try a simple test example and add to it to see when it breaks. I’m thinking:
-
Re-confirm files from github zip file are correct in org
-
Instantiate the exact “Test Date” from your gif – no inputFields, nothing. Just the bare minimum to getting a working copy in a VF page.
What would a stripped down DatePickerWrapper look like without an object?
Regards, Joshua
In the $Lightning.use code, you need to refer to a specific id so the javascript knows where to attach the picker to.
So you will need as many $Lightning.use calls as you have items in the apex:repeat. You could try putting a lightning use call inside the repeat and using the special id syntax to refer to it.
ie: <apex:page id="myPage"> <apex:variable value="{!1}" var="rowNum"/> <apex:repeat id="myRepeat"> <apex:inputText value="{!something}" id="inputDate"/>
<apex:variable var="rowNum" value="{!rowNum + 1}"/> </apex:repeat>
So the tricky part is building that id, since it is generated dynamically. In this instance, you would need to build up the string and it would be something like: "myPage:myRepeat:" + {!rowNum} + "myInput". Since there is no rowNum in Visualforce, you have to do you own:
Add this above the repeat: <apex:variable value="{!1}" var="rowNum"/>
Inside the repeat, increment it. <apex:variable var="rowNum" value="{!rowNum + 1}"/> (I've already added it above).
Hopefully you can take this example and just use it.
Note, this could quite heavy - one picker for each field. Another option is to use lazy loading and add the picker in an onclick attribute on the code. You may even be able to pass the id in the onclick call, which would save a lot of fussing.
A snippet: <apex:inputText value="{!something}" id="inputDate" onclick="handleClick(this.id)"/>
What you probably don't realise is that Visualforce takes your id actualFinal
and rewrites it.
It comes out as a concatenation of all the ids in the objects wrapping your field.
Hence this line in my example above:
"myPage:myRepeat:" + {!rowNum} + "myInput", //<--id is here
This evaluates to "myPage:myRepeat:1:myInput"
You can check this by rightclicking on the page and choosing "Inspect Element".
Look here for more info: https://developer.salesforce.com/forums/?id=906F000000098xKIAQ
Oh, btw, there is a bug in that string concatenation too. Change
"myPage:myRepeat:" + {!rowNum} + "myInput", //no colon
To
"myPage:myRepeat:" + {!rowNum} + ":myInput", //see added colon
Another option is to not use apex:outputText elements. If you use standard HTML elements, their ids won't be rewritten by Visualforce. Ie, your id actualFinal
will remain just that.
I also noticed a bug. Change your attribute to:
<aura:attribute name="review"
type="Custom_Review__c"
default="{'sobjectType' : 'Custom_Review__c',
'recordType.Name' : 'Special_Review',
'Actual_Final_Signature__c' : ''}"
/>
Caspar, This has been a great opportunity to learn more about lightning. I think I’m starting to know my way around the Chrome dev tools. I got a little further before I hit a snag. Using the inspect element, I confirmed I was passing the right element Id. Then I switched to see the console in the dev tools and reloaded the page and got this:
GET https://*******visual.force.com/c/DatePickerApp.app?aura.format=JSON&aura.formatAdapter=LIGHTNING_OUT 404 (Not Found) use @ lightning.out.delegate.js?v=YfjoKfTjN2bVGUBUXXcoWw:156 use @ lightning.out.js?v=2:59 (anonymous) @ SpecialReview?isdtp=p1&sfdcIFrameHost=web&id=a3Jr00000000HUOEA2&vfRetURLInSFX=%2Fa3Jr00000000HUOEA2&…:313
I read up on this error and it seemed I needed to use extends=”ltng:outApp” in the app. I removed the slds and added that and the dependency of DatePickerWrapper. That got past that error, but then datestr from DatePickerController line 19 returned undefined, which meant momentDate was null. The page actually threw an error for the $A.getCallback() call later on in the controller for no locater provided, although I couldn’t find docs to determine what that method params were.
Last thing, in looking through the DatePicker component, line 37 still references for=”closedate”. Which I think is from your github example.
Updated script: $Lightning.use("c:DatePickerApp", function() { $Lightning.createComponent( "c:DatePickerWrapper", {value : "{!review.Actual_Final_Signature__c}", callback : function(){ alert('callback'); } }, "page:form-ltng:actualFinal", function(cmp) {}); });
Updated DatePickerWrapper: <aura:component access="global"> <aura:attribute name="review" type="Custom_Review__c" default="{'sobjectType' : Custom_Review__c ', 'recordType.Name' : 'Special_Review', 'Actual_Final_Signature__c' : ''}" /> <aura:handler name="dateChangeEvent" event="c:DateChange" action="{!c.handleDateChange}" /> <aura:attribute name="callback" type="String" description="Call this to communicate results to visualforce page" access="global"/>
Updated DatePickerApp: <aura:application extends="ltng:outApp"> <aura:dependency resource="c:DatePickerWrapper"/> </aura:application>
Console log: [cid:[email protected]]
Regards, Joshua
I also noticed a bug. Change your attribute to:
<aura:attribute name="review"
type="Custom_Review__c"
default="{'sobjectType' : 'Custom_Review__c',
'recordType.Name' : 'Special_Review',
'Actual_Final_Signature__c' : ''}"
/>
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/rapsacnz/DatePicker/issues/5#issuecomment-288234733, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AHKJKMA7RAS8kjDXjFOFNC-fIC0EK22Lks5roEo_gaJpZM4MhTAV.
For line 37 of the component, you should probably change that to the id of the date - I've also done that in the repo - Thanks. In the controller, line 19, the date will be null if you are not passing in a datestring - which is fine, as the component will then generate a new default date - today's date. Is that how it's working? Either way, I don't think there's a problem there. Glad you are getting some good Lightning experience - it's a pretty cool component framework. Also, look out for my new component I'm making at the moment - a two column, draggable, multi select component (as opposed to the drop-down style one I made a while back).
Caspar, I believe you have a great start here, but having debugged this using the Chrome Dev Tools, I am positive this app is not set up from VF in its current state and implementation. Hopefully these will help improve your component.
Current Bugs for VF implementation:
- There is a 404 error because the app does not extend ltng:outApp.
- Dates do not transer from VF page to DatePickerController datestr.
- If I manually entered a date string in the DatePickerWrapper instead of {!v....}, then this error occurs.
This page has an error. You might just need to refresh it. Error during init [Action failed: c:DatePicker$controller$doInit [momentDate.isValid is not a function]]
Aura documentation shows isValid is used for components. Maybe a leftover from Moment.js?
- If momentdate.isValid() is removed from the null check, then this error occurs
This page has an error. You might just need to refresh it. Error during init [Action failed: c:DatePicker$controller$doInit [momentDate.toDate is not a function]]
Because momentDate is already a date, since that is what is returned by $A.localizationService.parseDateTime().
If that is removed so that the line 24 reads "currentDate = momentDate;", then no errors occur, but the component never builds in the vf page.
- I tried to confirm if the dateChangeEvent ever fires on init to be handled by the wrapper controller and callback to the vf page. I didn't see it, but it may be there or not need to be explicit. So this may or may not be a bug.
Also tried with the html tag and a generic testDate variable from the Apex controller.
Lastly, to verify org config, built the app out of the lightning documentation on using components in VF pages, and had no issue showing the "Press Me" button.
I do look forward to hearing if you get this one running or about your other component's release. This has been a learning experience either way for me.
Regards, Joshua
Hi Joshua, As regards point 1, that is not a bug - it's just something you need to do to use in a VF page. For the others, I'll spin up a demo VF page on Monday and get it working - if there is anything to be fixed, I'll fix it and let you know. You are probably right about some of these bugs - in my production code I've fixed a few bugs and some of the fixes may not have made their way here. I'll let you know.
Thanks, Caspar! I appreciate your work on this.
Ok, there were several issues caused by divergence of my production code and this code. The worst was actually a bug caused by the framework in it's parsing of dates. It appears that they have moved to returning a Javascript Date object rather than a Moment.js object. This caused a lot of problems. I have added in things added in my production code also:
-- better drop down handling -- clear date function -- manual input handling -- use of a custom select object (included) that allows the component to display the currently selected year. -- removal of Resource dependencies (using the built in lightning css) -- probably some other stuff :)
I needed to do this, because one of my other production projects used the same "no moment dependencies" build, so will now be breaking until I update it with this latest code.
Please use the attached VF page, TestDatePicker component and App, and TestDatePicker Apex controller to check it's all working for you.
Cheers,
Caspar
A date picker displays!
Still having a couple probable bugs. Initially, it would not compile Select.cmp because there was no markup for "DataChange". I assumed you meant "DateChange", but I'm not sure. When the default date in TestDatePicker is removed, I ran into an error for timezone being undefined. Maybe it's not passed to parseInputDate? Also, when I select a year, it crashes the page. I get a warning that Event.setParams(): 'data'('2017') is not a valid parameter. Valid parameters are 'value'.
Much improved though to get a displayed date picker in a vf with the confirmed callback.
I've added a new DataChange event. You should probably update every component with what's up here, because much has changed. Oh and I see DataChange is not up... I'm putting up now.
Ok, you were right! There was a bug when a value was cleared... also it would attempt to add todays date in if you cleared, which you would not want - if you clear it, you want it to stay cleared! So yeah, get fresh sources for the datepicker, the events, and the select and you should be good to go.
@sfdcDesign is it working for you?
@rapsacnz Thanks for the updated version...current development on that page got tabled for a couple sprints. I'm still going to test in some free time on a test page. I'll let you know. Thanks!