Thursday, September 29, 2016

Published my first SharePoint Framework client webpart to Public CDN

The new SharePoint Framework is cool and awesome. I developed my first SPFx webpart and published the files to public CDN.

Followed the below amazing articles to fetch the lists from site and deploy to public CDN.
As the files are deployed to public CDN, no need to run the gulp serve on your local environment.
The code is present in my Github repository

https://github.com/akashkarda/Samples/tree/master/helloworld-webpart


Client Webpart:


Public CDN:



The App Catalog:

Monday, November 9, 2015

Using AngularJS and REST to display list data in SharePoint hosted app

AngularJS is now best way to work on the MVC pattern at client side. In this post, I will walk you through how we can display the data from a SharePoint list in a SharePoint hosted app using AngularJS and SharePoint REST. My assumption is that you have basic understanding of AngularJS and SharePoint REST.
  • Create a SharePoint hosted app.
  • Create a Contacts List in app web.
  • Add a reference of AngularJS to default.aspx
In the default.aspx, add the below code.

  <div ng-app="myApp">  
     <div ng-controller="customersCtrl">  
       <table>  
         <tr>  
           <th>Last Name</th>  
           <th>First Name</th>  
         </tr>  
         <tr ng-repeat="x in Contacts">  
           <td>{{ x.Title }}</td>  
           <td>{{ x.FirstName }}</td>  
         </tr>  
       </table>  
     </div>  
   </div>  

In the above code, ng-app is used to specify that its an AngularJS app and ng-controller is the controller.

Add the below code in the App.JS file.


 'use strict';  
 var myapp = angular.module('myApp', []);  
 myapp.controller('customersCtrl', function ($scope, $http) {  
   var restUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('Contacts')/items?$select=Title,FirstName"; 
   $http({  
     method: "GET",  
     url: restUrl,  
     headers: { "Accept": "application/json;odata=verbose" }  
   }).success(function (data) {  
     $scope.Contacts = data.d.results;  
   }).error(function (sender,args) {  
     alert("Error:" + args.message);  
   });  
 });  
 function getQueryStringParameter(paramToRetrieve) {  
   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] == paramToRetrieve)  
       return singleParam[1];  
   }  
 }  

Change the restUrl to below if you wanted to query Host Web.

   var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));

   var restUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/SP.AppContextSite(@target)" + "/web/lists/getbytitle('Contacts')/items?$select=Title,FirstName,Company" +  "&@target='" + hostUrl + "'";


In the above code, we are getting the results from the contacts lists and assigning it to Contacts collection of $scope.
Add few items in the contacts lists by navigating to Lists/Contacts url






















Run the code, the results of the code is something like below


Wednesday, November 4, 2015

Get app web and host web title using jQuery promises in SharePoint hosted app

In my previous post, I talked about getting the app web title using jQuery promises. In this post we will talk about how to get the app web as well as host web title using jQuery promises in SharePoint hosted app.

Below is the simple code to get the title of both the web.

 var def = $.Deferred();  
 $(document).ready(function () {  
   var promise = GetHostWebTitle();  
   promise.then(  
     function (hostTitle, appTitle) { $('#message').text("Host web title : " + hostTitle+ ". App web Title : "+ appTitle) },  
     function (result) { $('#message').text("Error :" + result) }  
     );  
 });  
 var appContext;  
 var hostContext;  
 var hostWeb;  
 var appWeb;  
 function GetHostWebTitle() {  
   //Get the host web url from query string  
   var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));  
   //Get context fro host web and app web  
   appContext = SP.ClientContext.get_current();  
   hostContext = new SP.AppContextSite(appContext, hostUrl);  
   //Get the abb web and host web  
   appWeb = appContext.get_web();  
   hostWeb = hostContext.get_web();  
   appContext.load(appWeb, "Title");  
   appContext.load(hostWeb, "Title");  
   appContext.executeQueryAsync(onHostWebSuccess, onHostWebFailed);  
   return def.promise();  
 }  
 function onHostWebSuccess(sender, args) {  
   var hostWebTitle = hostWeb.get_title();  
   var appWebTitle = appWeb.get_title();  
   def.resolve(hostWebTitle, appWebTitle);  
 }  
 function onHostWebFailed(sender, args) {  
   def.reject(args.get_message());  
 }  
 function getQueryStringParameter(paramToRetrieve) {  
   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] == paramToRetrieve)  
       return singleParam[1];  
   }  
 }  

Once you run the above code, you will get the error as Access Denied on host web.












To resolve this issue, make sure you grant read access to the host web using AppManifest file.












Once you granted the access, the output result will show you the host web and app web title.














In the above example we are getting the host web context by using the below line.

 hostContext = new SP.AppContextSite(appContext, hostUrl); 

Also, you can pass multiple parameters when your deferred is resolved. In the above example, I am passing two parameters to the call back function.

 def.resolve(hostWebTitle, appWebTitle);  

Using jQuery Deferred and Promises in SharePoint Hosted App

jQuery promises are awesome when you wanted to work with aysnc calls in SharePoint hosted app.

Below is the simple example to get the App web title in SharePoint 2013 using jQuery Promises.

 var def = $.Deferred();  
 $(document).ready(function () {  
   var promise = GetAppWeb();  
   promise.then(  
     function (result) { $('#message').text("The app web title is " + result) },  
     function (result) { $('#message').text("Error :" + result) }  
     );  
 });  
 var appContext;  
 var appWeb;  
 function GetAppWeb()  
 {  
   appContext = SP.ClientContext.get_current();  
   appWeb = appContext.get_web();  
   appContext.load(appWeb);  
   appContext.executeQueryAsync(onAppWebSuccess, onAppWebFailed);  
   return def.promise();  
 }  
 function onAppWebSuccess(sender, args)  
 {  
   var title = appWeb.get_title();  
   def.resolve(title);  
 }  
 function onAppWebFailed(sender,args)  
 {  
   def.reject(args.get_message());  
 }  

You can also use .done and .fail instead of .then function. The output of the above solution is as below


Wednesday, July 15, 2015

Setup a development environment for Apps in SharePoint 2013

As Apps require a DNS entry, it is difficult to create a DNS entry for development environment. Below is the post which will guide you to setup a development environment for apps without DNS entry(using hosts file).

1. Add entry in hosts file.

Add a below entry in hosts file (C:\Windows\Systems32\drivers\etc)

127.0.0.1    apps.servername.com

where servername.com is Full Computer Name(which we can get by using Computer Properties)
















2. Modify Registry entry

Open the registry editor by typing regedit in the command prompt.
Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
Add a new DWORD with Key  DisableLoopbackCheck
Edit and set its value to 1 (Decimal)
Re-Start your machine

3. Start the service

Run the below command in SharePoint powershell to start Admin, Timer , Apps and Subscription service

 net start spadminv4  
 net start sptimerv4  
 Get-SPServiceInstance | where{$_.GetType().Name -eq "AppManagementServiceInstance" -or $_.GetType().Name -eq "SPSubscriptionSettingsServiceInstance"} | Start-SPServiceInstance  


4. Create a app management and substription service application

 $account = Get-SPManagedAccount "domain\user"   
 $appPoolSubSvc = New-SPServiceApplicationPool -Name SettingsServiceAppPool -Account $account  
 $appPoolAppSvc = New-SPServiceApplicationPool -Name AppServiceAppPool -Account $account  
 $appSubSvc = New-SPSubscriptionSettingsServiceApplication -ApplicationPool $appPoolSubSvc -Name SettingsServiceApp -DatabaseName SettingsServiceDB   
 $proxySubSvc = New-SPSubscriptionSettingsServiceApplicationProxy -ServiceApplication $appSubSvc  
 $appAppSvc = New-SPAppManagementServiceApplication -ApplicationPool $appPoolAppSvc -Name AppServiceApp -DatabaseName AppServiceDB  
 $proxyAppSvc = New-SPAppManagementServiceApplicationProxy -ServiceApplication $appAppSvc  

where domain\user is the managed account name

5. Setup app domain 

Go to central administration site. On left navigation click "Apps".
Click on Configure App URLs in App Management.
Setup the app domain














You can also use below command to setup using powershell.

 Set-SPAppDomain "app.servername.com"  
 Set-SPAppSiteSubscriptionName -Name "app" -Confirm:$false  

6. Create an App

Open visual studio and create a new project, give a name as HelloWorldApp

















Provide the name of app.
Provide the development site SharePoint url
Select SharePoint-hosted as a hosts

















Click Finish.

Run the solution by clicking F5. The solution will run and you can see the app.




Monday, March 16, 2015

Date column showing incorrect value for different timezone using javascript object model in SharePoint 2013

When you have multiple users in different zones, you will see the date value varies based on different timezone. The date which we are getting using javascript object model shows the local computer time and not the server time.

Suppose I have a list with column named "DateCompleted". I have added a new row with DateCompleted as 3/16/2015 12:00 AM.

When you use javascript client object model and display the date in web page. The result for teh below lines varies by differnt timezone.

var dateCompleted = oListItem.get_item('DateCompleted');

EST Timezone = > dateCompleted =  3/16/2015 12:00 AM.   (Server time)
PST Timezone = > dateCompleted =  3/15/2015 09:00 PM. 

To resolve the issue and display always the server time, you need to query the list again and use SP.Utilities.Utility.formatDateTime function. 

Below is the code you can refer to get the server time.

1:    var ctx = new SP.ClientContext(spotTargetSiteUrl);  
2:    var web = ctx.get_web();  
3:    var dateCompleted = oListItem.get_item('DateCompleted');  
4:    var dateStr = SP.Utilities.Utility.formatDateTime(ctx, web, dateCompleted, SP.Utilities.DateTimeFormat.dateOnly);  
5:    ctx.executeQueryAsync(  
6:       function (sender, data) {  
7:            // the below line will give you the server time  
8:           var serverDateCompleted = new Date(dateStr.m_value);  
9:       },  
10:       function (sender, args) {  
11:         ULSOnError(args.get_message(), document.location.href, 0);  
12:       }  
13:       );  

The line 8 above will give you the server time.

Hope this post will help you in resolving the date issue for different timezone.

Happy coding!!!!

Tuesday, June 24, 2014

Create Lookup Site Column using Javascript object model in SharePoint 2013 / 2010

Sometimes we need to create a lookup column as a site column to use it in different list or use it in a content type. Below is a simple code to create a Lookup site column using javascript object model. The code works in both SharePoint 2010 and SharePoint 2013 environment.


 jQuery(function($) {   
        CreateSiteLookupColumn();   
 });   
      var clientContext;  
      var oWebSite;  
      var oList;  
      function CreateSiteLookupColumn()  
      {  
         clientContext= new SP.ClientContext.get_current();   
         oWebSite= clientContext.get_web();  
         //Lookup List  
         oList=oWebSite.get_lists().getByTitle('Countries');  
         clientContext.load(oList);  
         clientContext.load(oWebSite);  
         clientContext.executeQueryAsync(function () {  
                 var fieldXml="<Field Name='Country' DisplayName='Country' Type='Lookup' Required='FALSE' Group='Operations'/>";  
                 var lookupField=oWebSite.get_fields().addFieldAsXml(fieldXml,true,SP.AddFieldOptions.addFieldCheckDisplayName);  
                //Cast to Lookup field to set List Name and lookup column       
                 var fieldLookup = clientContext.castTo(lookupField, SP.FieldLookup);  
                 fieldLookup.set_lookupList(oList.get_id());  
                 fieldLookup.set_lookupField("Title");  
                 fieldLookup.update();              
                 clientContext.executeQueryAsync(function () {   
                         alert('Field Added');   
                      }, function (sender, args) {   
                            alert(args.get_message() + '\n' + args.get_stackTrace());   
                      });   
         },function (sender, args) {   
          alert(args.get_message() + '\n' + args.get_stackTrace());   
      });     
 }