Monthly Archive March 2015

AvatarByRashid Aziz

Create Managed Property from Crawl Property in SharePoint 2013 Search via PowerShell

I have some custom properties in User Profile. I needed to create managed properties in SharePoint 2013 from custom user profile Crawl properties. I really don’t like doing things manually using SharePoint 2013 central administration site because then I have to recreate these properties on all different environments manually. So here is the script which will do the magic

User profile property name: City 

Crawl property display name: People:City

Crawl property full name: urn:schemas-microsoft-com:sharepoint:portal:profile:City 

You can get the crawl property full name from central admin UI

(Click on “search schema” link from search administration page 

Click “Crawled Properties” link

Search for your property, once it appear in result, click on it.

Crawl property detail page will open and will display the “Property Name” something like “urn:schemas-microsoft-com:sharepoint:portal:profile:City”) 

// Get the search service application

$searchapp = Get-SPEnterpriseSearchServiceApplication

// create base managed property 

$managedProperty_City= New-SPEnterpriseSearchMetadataManagedProperty -Name "City" -SearchApplication $searchapp -Type 1 -Queryable $true -Retrievable $true -FullTextQueriable $true

//Set “Refineable” and “Sortable” properties to true for this newly created managed property, by default these values will be set to false. You can skip this step if you don’t want to set the values to true

$managedProperty_City.Refinable=$true

$managedProperty_City.Sortable=$true

$managedProperty_City.Update()

//Get the crawl property which already exist and map it to the newly created managed property

$crawlProperty_City= Get-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $searchapp -Limit 1 -Name "urn:schemas-microsoft-com:sharepoint:portal:profile:City"

New-SPEnterpriseSearchMetadataMapping -SearchApplication $searchapp -ManagedProperty $managedProperty_City -CrawledProperty $crawlProperty_City

Once you run these command, go to search schema page and search for the new managed property “City”. You should see the following result

 

Reference to get parameters detail: https://technet.microsoft.com/en-us/library/ff608089.aspx 

 

AvatarByRashid Aziz

Interactive JavaScript Maps Integration with SharePoint 2013 using Script Editor Web Part

I have a top level SharePoint site called “Our Offices” and sub site for each country office location (e.g. London, Berlin etc.). The “Our Offices” site home page needs to provide easy navigation to all offices sub sites. Also, I wanted to show where this office location reside on the world map and when someone click on the location, system should redirect the user to that location site home page. 

To do this I have used AmMap solution. The JavaScript / HTML5 mapping library (jsmap) help to create interactive, animated maps and display them in your web sites or web applications.

Navigate to http://www.amcharts.com/javascript-maps/ and click on download button.  

 On the next page, click “Interactive JavaScript Maps” download link as highlighted below.

 Once downloaded, extract the zip folder and give the root folder a proper name.  (By default it will be something like “ammap_3.13.1.free”. I have renamed the root folder to “CoolMaps”)

Copy the “CoolMaps” folder, Navigate to SharePoint 15 hive Layouts folder (C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\LAYOUTS) and past the “CoolMaps” folder here.

Add “Script Editor” web part on “Our Offices” site home page.

 

 Copy and paste the following code into your script editor web part.

Note: Please updated the locations and SharePoint sub site URLs as per your business requirements.

<link rel="stylesheet" href="/_layouts/15/CoolMaps/ammap/ammap.css" type="text/css">
        <script src="/_layouts/15/CoolMaps/ammap/ammap.js" type="text/javascript"></script>
        <!-- map file should be included after ammap.js -->
	<script src="/_layouts/15/CoolMaps/ammap/maps/js/worldLow.js" type="text/javascript"></script>

		<script type="text/javascript">
			var map;

			// svg path for target icon
			var targetSVG = "M9,0C4.029,0,0,4.029,0,9s4.029,9,9,9s9-4.029,9-9S13.971,0,9,0z M9,15.93 c-3.83,0-6.93-3.1-6.93-6.93S5.17,2.07,9,2.07s6.93,3.1,6.93,6.93S12.83,15.93,9,15.93 M12.5,9c0,1.933-1.567,3.5-3.5,3.5S5.5,10.933,5.5,9S7.067,5.5,9,5.5 S12.5,7.067,12.5,9z";

			AmCharts.ready(function() {
			    map = new AmCharts.AmMap();
			    map.pathToImages = "/_layouts/15/CoolMaps/ammap/images/";

			    map.imagesSettings = {
			        rollOverColor: "#FFA02F",
			        rollOverScale: 3,
			        selectedScale: 3,
			        selectedColor: "#FE5815",
                                color: "#FE5815"
			    };

			    var dataProvider = {
			        mapVar: AmCharts.maps.worldLow,
			        images: [
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"London", latitude:51.5002, longitude:-0.1262, url: "../London"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Paris", latitude:48.8567, longitude:2.3510, url: "../Paris"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Berlin", latitude:52.5235, longitude:13.4115, url: "../Berlin"},	
{svgPath:targetSVG, zoomLevel:5, scale:0.5, title:"Amsterdam", latitude:52.3738, longitude:4.8910,  url: "../Amsterdam"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Singapore", latitude:1.2894, longitude:103.8500, url: "../Singapore"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Islamabad", latitude:33.6751, longitude:73.0946, url: "../Islamabad"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Beijing", latitude:39.904030, longitude:116.40752599, url: "../Beijing"},	
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Tokyo", latitude:35.6785, longitude:139.6823,  url: "../Tokyo"},				   
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Chicago", latitude:41.87811360, longitude:-87.6297981999, url: "../Chicago"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Bucharest", latitude:44.4479, longitude:26.0979, url: "../Bucharest"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"Moscow", latitude:55.7558, longitude:37.6176, url: "../Moscow"},
{svgPath:targetSVG, zoomLevel:5, scale:1.0, title:"San Marino", latitude:43.9424, longitude:12.4578, url: "../SanMarino"}
			        ]
			    };
			    map.dataProvider = dataProvider;

			    map.objectList = new AmCharts.ObjectList("listdiv");
			    map.showImagesInList = true;

			    map.write("mapdiv");

			});

        </script>
    <div>
        <div id="listdiv" style="width:200px; overflow:auto; height:500px; float:right; background-color:#FFFFFF;"></div>
        <div id="mapdiv" style="margin-right:200px; background-color:#FFFFFF; height: 500px;"></div>
    </div>
<br/>

 

Save the page and publish it. 

The Map should appear like this on the page

 

On mouse hover it will highlight the location on the map and when user click on a location, it will take you to pre-configured sub site for that location. 

The map I am showing here is just for demo purpose. There are many more types of maps available in this library. Go and explore the rest Smile

AvatarByRashid Aziz

Angular JS and Bootstrap to Display SharePoint 2013 List Data using Script Editor

I am big fan of using OOTB stuff, but sometime customer want to see things in different way or their organisational design guidelines are difficult to achieve using OOTB functionality.

In my previous post I have explained how to customise SharePoint list form using Angular JS and Bootstrap 

Here, I will show you how to display list items using bootstrap and AngularJS.  I have picked a scenario: I have SharePoint 2013 list called “Customer Details”. The list have following columns

Schema name

Display name

Title

Customer name

City

City

Country

Country

ContactPerson

Contact person

 

The list default OOTB view appear as below

The customer want to display this list data on a page but with complex UI design. OOTB list web part will only display the data in same way as it appears in the list view.

One way to achieve the complex design is by using AngularJS and Bootstrap.

1.  Create a new page inside SharePoint 2013 site “Pages” library.

 2.  Add a “Script Editor” web part on the page

3.  Copy and paste the following code inside script editor web part

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>  
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
 
<script>
    var angApp = angular.module('SharePointAngApp', []);
    angApp.controller('spCustomerController', function ($scope, $http) {
        $http({
            method: 'GET',
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('Customer Details')/items?$select=Title,City,Country,ContactPerson",
            headers: { "Accept": "application/json;odata=verbose" }
        }).success(function (customerData, status, headers, config) {
            $scope.customers = customerData.d.results;
        }).error(function (customerData, status, headers, config) {
      
        });
    });
   
</script>
    <link data-require="bootstrap-css@*" data-semver="3.0.0" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />
	 <div ng-app="SharePointAngApp">
	 <div ng-controller="spCustomerController">
	 <br/>
        <table class="table table-striped table-hover">
            <tr>
                <th>Customer name</th>
                <th>City</th>
                <th>Country</th>
				 <th>Contact person</th>
              
            </tr>
            <tr ng-repeat="customer in customers">
                <td>{{customer.Title}}</td>
                <td>{{customer.City}}</td>
                <td>{{customer.Country}}</td>
				<td>{{customer.ContactPerson}}</td>
                </tr>
        </table>
    </div>
	</div>


Now, the list data will appear as below inside script editor web part.

AvatarByRashid Aziz

SharePoint 2013 Custom List Form using Angular JS and Bootstrap

According to  Microsoft InfoPath Forms Services for SharePoint Server 2013 will be supported until April 2023. Keeping that in mind I have started looking into alternatives to build rich form which can be used with SharePoint list and replace OOTB form. I have started looking into Angular JS (AngularJS is a JavaScript framework. AngularJS extends HTML attributes with directives and binds data to HTML with expressions). From user interface point of view I spend some time with bootstrap (Bootstrap makes front-end web development faster and easier).

In the below example, I will use both AngularJS and Bootstrap to build custom SharePoint 2013 form to create new list items.

For this demo purpose, I will use SharePoint page with “Script Editor” to build this form. I highly recommend to use visual studio to build .aspx and .js files and update list schema to change lists default New/Edit forms.

1.Create “Customer Details” list which have the following column

Schema name

Display name

Title

First name

LastName

Last name

Address

Address

 

2.     Now create a new page in SharePoint 2013 “Pages” library. 

 

3.     Add “Script Editor” web part on the page.

 

4.     Copy and paste the following code inside script editor

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>  
<script>  
    function mainController($scope) {  
  
        $scope.customer = { firstName: "", lastName: "", location: "" };  
        $scope.createContact = function ($event) {  
            var c = $scope.customer;  
            $event.preventDefault();  
  
            var clientContext = new SP.ClientContext.get_current();  
            var web = clientContext.get_web();  
            var list = web.get_lists().getByTitle('Customer Details');  
            var customerListItemInfo = new SP.ListItemCreationInformation();  
            var listItem = list.addItem(customerListItemInfo);  
            listItem.set_item('Title', c.firstName);  
            listItem.set_item('LastName', c.lastName);
             listItem.set_item('Address', c.address); 			 
            listItem.update();  
            clientContext.executeQueryAsync(  
                Function.createDelegate(this, onQuerySucceeded),  
                Function.createDelegate(this, onQueryFailed)  
            );  
  
        };  
  
        onQuerySucceeded = function () {  
            alert('Successfully created new customer record');  
        }  
  
        onQueryFailed = function (sender, args) {  
            alert('Failed: ' + args.get_stackTrace());  
        }  
    }  
</script>  
  
<h2>Customer Information:</h2>  
<br />  
<div ng-app="">  
    <div ng-controller="mainController">  
        First name  
        <input type="text" ng-model="customer.firstName" /><br />  
        <br />  
        Last name
        <input type="text" ng-model="customer.lastName" /><br />  
        <br />  
        Address
		<input type="text" ng-model="customer.address" /><br />  
        <br />  
        <input type="submit" value="Save" ng-click="createContact($event)" />  
    </div>  
</div>

 

5.     Save the page and publish it. The form will look something like this.

You can now go ahead and start using the form to create new customer records, but I like to make the user interface a little better.

To do that, I have added bootstrap css library reference and added some classes with html elements.

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>  
<script>  
    function mainController($scope) {  
  
        $scope.customer = { firstName: "", lastName: "", location: "" };  
        $scope.createContact = function ($event) {  
            var c = $scope.customer;  
            $event.preventDefault();  
  
            var clientContext = new SP.ClientContext.get_current();  
            var web = clientContext.get_web();  
            var list = web.get_lists().getByTitle('Customer Details');  
            var customerListItemInfo = new SP.ListItemCreationInformation();  
            var listItem = list.addItem(customerListItemInfo);  
            listItem.set_item('Title', c.firstName);  
            listItem.set_item('LastName', c.lastName);
             listItem.set_item('Address', c.address); 			 
            listItem.update();  
            clientContext.executeQueryAsync(  
                Function.createDelegate(this, onQuerySucceeded),  
                Function.createDelegate(this, onQueryFailed)  
            );  
  
        };  
  
        onQuerySucceeded = function () {  
            alert('Successfully created new customer record');  
        }  
  
        onQueryFailed = function (sender, args) {  
            alert('Failed: ' + args.get_stackTrace());  
        }  
    }  
</script>  
      <link data-require="bootstrap-css@*" data-semver="3.0.0" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />
<h2>Customer Information:</h2>  
<br />  
<div ng-app="">  
    <div ng-controller="mainController" class="col-xs-5 selectContainer form-group">  
        First name  
        <input type="text" ng-model="customer.firstName" class="form-control"/><br />  
        <br />  
        Last name
        <input type="text" ng-model="customer.lastName" class="form-control" /><br />  
        <br />  
        Address
		<input type="text" ng-model="customer.address" class="form-control" /><br />  
        <br />  
        <input type="submit" value="Save" ng-click="createContact($event)" class="btn btn-primary btn-lg active" />  
    </div>  
</div>

You can see the difference as it look more professional after adding couple of bootstrap css classes.

 

I hope the above demonstration is helpful. Smile