Saturday, June 28, 2014

Hello LAMP with Codio


Codio has just announced that their web-based IDE is out of beta. They claimed that I could have a full LAMP stack set up in seconds. Zend made similar claims about their PHPCloud (which is now killed off by Zend) and while I did get it working and am a fan, it took some head scratching before I got it going. So, I set out to to get a “Hello LAMP” application working in Codio. It turned out to be fairly straightforward.

Here is what I did along with a link to the public project. You can check out all the Codio features and project settings etc. on the Codio site.
  1. Sign up for a free Codio account
  2. Click Create Project from the Dashboard, enter a project name and choose the PHP Project template. I kept this one Public. (Public means anybody can view it but they can’t edit it. Read more about that on their website). Click Create Project:

    image
  3. A project will almost instantly be created for you. Click on index.php in the Filetree and you will see that they have a “Hello PHP” already there for you. Right-click on index.php and select “Set as project index”. If you try to run this, you will be out of luck because you still need the A in LAMP. On the top menu bar click Tools –> Terminal and plug this in:

    2014-06-28_16-07-40
  4. You still wont be able to play your app because Apache isn’t running. This is spelled out to you in the terminal after the parts are installed. Do what it says AND switch your run option to “Box URL” AND… you still won’t be able to play your app!:

    image
  5. Don’t despair, there’s one more part to install ‘php5-apache2’ and then restart Apache:

    image
  6. Run the app via Box URL and VIOLA!

    image

  7. The name of this blog post is “Hello LAMP” so let’s start the M here:

    image

    image
  8. Create a database and then create your table and put at least a row in it:

    image
  9. Add your PHP code to index.php for reading and echoing your text from the database table:

    image

  10. Run your code and…

    image

The public project is out on Codio and you can check it out here: https://codio.com/joeldpalmer/PHP-Test
I’m pretty impressed with Codio as of now. If they add an integrated PHP debugger, that will make it a complete PHP IDE.


Bye PHP Cloud. I had high hopes. :-(

Friday, June 13, 2014

Sorting Grid Columns in LightSwitch apps Hosted on SharePoint 2013

Get grids to load pre-sorted and still allow users to re-sort via the column headers:
  1. Remove any sorts from the Query Designers but leave any desired filters:

    LS QueriesQueryDesigner
  2. For each Query, click the ‘Write Code’ drop down and find the PreprocessQuery method and it will add the declaration to the C# SPPurchaseReqDataService class
  3. Set the query value with LINQ:
     partial void QueryNewPR_PreprocessQuery(ref IQueryable<PurchaseRequisition> query)  
         {  
           query = query.OrderByDescending(p => p.Modified);  
         }  
     partial void QuerySubmittedPR_PreprocessQuery(ref IQueryable<PurchaseRequisition> query)  
         {  
           query = query.OrderByDescending(p => p.Modified);  
         }  

That's it. It's pretty straightforward once you do it but LightSwitch can be a bit confusing, at least for me. In theory, this code is supposed to do exactly what the Query Designer does. But, doing it in code (on the server-side) allows the users to re-sort whereas the designer lets the user believe they can re-sort but the grid is just reloaded with the original sort. I am able to repro this 100% of the time. I’m guessing that I am not the only one. If this is a known bug and/or if it is/gets fixed, please let me know. In any case, I hope this is still useful information on sorting in LightSwitch.

Wednesday, June 4, 2014

Display SharePoint App Web List Data in an App Part on the Host Web

At the time of this writing, I've seen a handful of posts that come close to what I needed but weren't quite there.

I needed to put an App Part on the Host that reads App Web list data, displays it in the App Part and contains links back to the App Web. This post from Corey Roth got me most of the way there. Thanks Corey!

To make sure you know exactly what I did, you should know that the fields, content types, list template and list instance are all part of the SharePoint-Hosted App project.

The code grabs the host and app web Urls and then loads up SP.js from the host. It queries the list and sticks the latest item's title in to a Marquee. This title is linked back to its associated display form on the app web list. I highly doubt you will come across these exact requirements but the plumbing should help.

Here is the full JavaScript source:

 var clientContext;  
 var siteCollection;  
 var collListItem;  
 var oList;  
 var appWebUrl;  
 $(document).ready(  
   function () {  
     var spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));  
     appWebUrl = decodeURIComponent(getQueryStringParameter('SPAppWebUrl'));  
     var layoutsRoot = spHostUrl + '/_layouts/15/';  
     $.getScript(layoutsRoot + "SP.Runtime.js", function () {  
       $.getScript(layoutsRoot + "SP.js", sharePointReady);  
     }  
     );  
     function sharePointReady() {  
       clientContext = SP.ClientContext.get_current();  
       oList = clientContext.get_web().get_lists().getByTitle('Notifications');  
       getList();  
     }  
   }  
 );  
 function getQueryStringParameter(urlParameterKey) {  
   var params = document.URL.split('?')[1].split('&');  
   var strParams = '';  
   for (var i = 0; i < params.length; i = i + 1) {  
     var singleParam = params[i].split('=');  
     if (singleParam[0] == urlParameterKey)  
       return decodeURIComponent(singleParam[1]);  
   }  
 }  
 function getList() {  
   var camlQuery = new SP.CamlQuery();  
   camlQuery.set_viewXml("<View><RowLimit>1</RowLimit><Query><OrderBy><FieldRef Name='Created' Ascending='False' /></OrderBy></Query></View>");  
   this.collListItem = oList.getItems(camlQuery);  
   clientContext.load(collListItem);  
   clientContext.executeQueryAsync(onRequestSucceeded, onRequestFailed);  
 }  
 function onRequestSucceeded() {  
   var lineBreak = document.createElement('br');  
   var listItemInfo = '';  
   var listItemEnumerator = collListItem.getEnumerator();  
   while (listItemEnumerator.moveNext()) {  
     var oListItem = listItemEnumerator.get_current();  
     var rightNow = new Date();  
     var expireDate = new Date(oListItem.get_item('NotificationExpiration'));  
     if (rightNow < expireDate) {  
       listItemInfo += "<marquee scrollamount=4>";  
       listItemInfo += '<a target=_blank href=' + appWebUrl + '/Lists/Notifications/DispForm.aspx?ID=' + oListItem.get_id() + '>' + oListItem.get_item('Title') + '</a>';  
       listItemInfo += "</<marquee>";  
       listItemInfo += "<br>";  
     }  
   }  
   $('#Notifications').html(listItemInfo);  
 }  
 function onRequestFailed(sender, args) {  
   alert('Error: ' + args.get_message());  
 }  
Helpful Resource: How to: Retrieve List Items Using JavaScript

On a side note, my Office 365 Developer Site is worth every penny. I used it to test and debug this code and it worked wonderfully.

JavaScript Scope: Function Evaluation


Function declarations are evaluated first and moved to the top of the scope during parsing. So, you can declare them anywhere in the body of the script and call them before the declaration:


Function expressions are not evaluated until assignment:


Like other variables, it is a good idea to define them at the top of the scope. But, with function expressions you must make the assignment before you make a call:


To sum it all up, take a look at the Locals window when execution starts:


The declared functions are evaluated and ready for calls as soon as script execution starts.