Tuesday 23 December 2014

Upgrade a SharePoint App after list field modification by its build version


It was quite challenging to upgrade  an app by its build version if some changes are made in the list structure.

Suppose I have an app which creates two lists(ListA,ListB) when it is deployed to a site collection. Now, I have deleted two columns in ListA and after some changes I would like to upgrade the app in that site collection.

Let me tell you, it will not allow you to upgrade that and after a while it will generate an error "taking too long time."

To solve this, you have to write your changes in Feature1.Template.xml as below:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/" Version="1.0.0.4">
  <UpgradeActions
    <VersionRange BeginVersion="1.0.0.3" >
      <ApplyElementManifests>
        <ElementManifest Location="PLinksInstance\Elements.xml" />
        <ElementManifest Location="PLinks\Elements.xml" />
        <ElementManifest Location="UserPLinkSettingsInstance\Elements.xml" />
        <ElementManifest Location="UserPLinkSettings\Elements.xml" />
      </ApplyElementManifests>
    </VersionRange>
  </UpgradeActions>

</Feature>

And Obviously you need to change the permission at AppManifest.xml as shown below:



Now Rebuild the project and publish to get the app package(.app file) and try to upgrade the app in "Apps In Testing" in the Site Contents of the site collection.

Hopefully, it will successfully upgrade the app.

Wednesday 17 December 2014

Create a Graphical Bar Chart in SharePoint Apps

The Graphical Case Overview gets the number of items in a list where the "MyColumn" column have a specific value. These counts are then displayed in a graph. A prototype have been implemented using Chart.js (http://www.chartjs.org/) which works very well.


Suppose we have a list named "MyList" and a Column named "MyColumn". The following figure illustrates the scenario:



Now, we need to create a graphical chart app (sharepoint hosted) by counting distinct value of the "My Column".


For that we need to get the items of specific column from the above list. We shall use JavaScript Object Model(JSOM) for this purpose:


function getDistinctItemsFromList() {

    //Get the SharePoint Context object based upon the URL
    var ctx = new SP.ClientContext(appWebUrl);

    //Get the List based upon the Title 
    var oList = ctx.get_web().get_lists().getByTitle('MyList');

    var camlQuery = new SP.CamlQuery();

    camlQuery.set_viewXml('');
    this.collListItem = oList.getItems(camlQuery);

    ctx.load(collListItem);
    ctx.executeQueryAsync(
        Function.createDelegate(this, this.onSuccess),
        Function.createDelegate(this, this.onFail)
    );
}



function onSuccess(sender, args) {

    var itemCount = collListItem.get_count();

    var itemsarry = new Array(parseInt(itemCount) - 1);

    var ListEnumerator = collListItem.getEnumerator();

    ColumnName = 'MyColumn';

    // adding values to array
    for (i = 0; i < itemCount; i++) {
        itemsarry[i] = new Array(0);
        itemsarry[i][0] = collListItem.get_item(i).get_item(ColumnName);
    }

    // getting count of unique values from array
    var uniqueItemsCount = 0;
    var uniqueItems = {};
    $.each(itemsarry, function () {
        var num = this[0];
        uniqueItems[num] = uniqueItems[num] + 1 || 1;
        uniqueItemsCount++;
    });

    //uniqueItems is your array with Column value and the associated Count.

    //uniqueItemsCount is how many of these distinct values exist which is 3 in            our case (Category A, Category B  and Category C)

    //Now to extract the values from this array use the snippet below
   
    $.each(uniqueItems, function (itemValue, noOfItems) {
        if (itemValue != 'undefined');
        {
            
           //Array of data to generate chart
            _arrayOfData.push(noOfItems);

            //Array of labels to generate chart
            _chartLabels.push(itemValue);
          
        }
     
     //Generates the graphical bar chart
     CreateChart(_arrayOfData,_chartLabels);

    });

   
    
}
function onFail(sender, args) {
    $("#results").html('<p>Error: ' + args.get_message() + '</p>');
}

And please add the following html structure in  .aspx page of your app part.

<body>
    <div id="results">

    </div>
    <div id="divChart">
    <canvas id="myChart" width="600" height="400"></canvas>
    </div>
</body>


And in the CreateChart function, assign the _arrayOfData and _chartLabels to another variable chartData.



function CreateChart(_arrayOfData,_chartLabels)
{

  var chartData = 
   {
     labels: _chartLabels,
     datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(151,187,205,0.5)",
            strokeColor: "rgba(151,187,205,0.8)",
            highlightFill: "rgba(151,187,205,0.75)",
            highlightStroke: "rgba(151,187,205,1)",
            data: _arrayOfData
        }
     ]
  };

var chartOptions =
 {
            scaleOverride: true,
            //set the maximum scale
            scaleSteps: Math.max.apply(Math, _arrayOfData), 
            scaleStepWidth: 1,          //set scale interval along Y axis
            scaleStartValue: 0,         // set starting scale value
            showLegend: true
}

       // Get context with jQuery - using jQuery's .get() method.

    var ctx = $("#myChart").get(0).getContext("2d");
    
   
    //Create instance of the Chart class with chartData and chartOptions

    var myBarChart = new Chart(ctx).Bar(chartData , chartOptions );

    $('#mychart').html(myBarChart);
}



And in the .aspx page, don't forget to put the references of the below links to generate the the chart properly.

 <!--jQuery library-->

    <script src="https://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/0.2.0/Chart.min.js" type="text/javascript"></script>


Call the getDistinctItemsFromList() method in appropiate place of the apps. It can be in apps.js file or your own js file as below:


// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model

$(document).ready(function () {

    appWebUrl = decodeURIComponent(manageQueryStringParameter('SPAppWebUrl'));
  

    //CreateChart by getting distinct elements and their counts from a sharepoint list
    getDistinctItemsFromList();

});


Finally, you should get the chart shown below if everything is putted in right place of the sharepoint apps.




Happy SharePointing................!!!