CHUVASH.eu

CHunky Universe of Vigourous Astonishing SHarepoint :)

Tag Archives: webpart

Export Any Web Part using a Bookmarklet

My blog post about exporting any webpart from a SharePoint Page is one of the most read articles on my blog. I use this method a lot. Now what I want to do is to simplify the process. Inspired by my colleague Dan Saedén’s awesome bookmarklet for reading and updating web properties, I decided to make my own bookmarklet. That was easy. Now we can export any web part from any SharePoint page without even looking at any ids in the html markup and assembling the export url manually. Just add the bookmarklet or run  the javascript code in the browser console. The code (js and bookmarklet) is on Github.

Here is an animated gif that explains how to use it:

export-webpart-002

Export any web part from a SharePoint page

The blog post below describes the technical details about how Web Parts can be exported using a hidden tool in OOB SharePoint, though this requires manual assembling of a special url. If you are just interested in a solution for an easy Web Part Export function, just proceed directly to my new blog post where you can download my tool that you can add to your web browser.

 

[youtube https://www.youtube.com/watch?v=wL9y9E1aJy0]

Technical background

Almost all web parts can be exported from a SharePoint page. An exported web part  can be imported on another page or it can be used as a source in a module to provision pages. An exception is the XsltListViewWebPart, there you cannot enable exporting. I have used Glyn Clough’s method before which has worked although it is a complicated process. Now I have found another way for exporting any web part (even ListViewWebPart and XsltListViewWebPart) present on a page. A method that only involves a web browser.

How to export any web part

First, we need to find out the webpartid. To do so inspect the html markup with the web browser dev tools of your choice.

export-webpart-001

In SharePoint there is a hidden application page that exports web parts: /_vti_bin/exportwp.aspx. This page takes two query parameters:

  • pageurl. The absolute url of the page where the web part resides that you want to export
  • guidstring. The guid that is called webpartid in the markup on the page

So, suppose, you have this site: https://intranet.contoso.com and a web part (id: 0c3adfe9-8f5d-4432-918a-42410e4e324d) on a page https://intranet.contoso.com/Pages/default.aspx

This will be the resulting URL to export your webpart:

https://intranet.contoso.com/_vti_bin/exportwp.aspx?pageurl=https://intranet.contoso.com/Pages/default.aspx&guidstring=0c3adfe9-8f5d-4432-918a-42410e4e324d

Paste it into the web browser address bar and you’ll download an xml file with your web part definition. This method works in SharePoint 2010 and SharePoint 2013 and even in SharePoint Online (Office 365).

Sources

Natalia Tsymbalenko. Get the list view web part convertable

Maurice Prather. Exporting a ListViewWebPart

SharePoint StackExchange

I am glad to update my answer on SharePoint StackExchange site and provide a much easier way of exporting any web part from SharePoint.

Bookmarklet (update 2015-10-21)

Finally there is a bookmarklet for making Web Part Export a lot easier. See my new blog post for more details:

AngularJS: prevent form validation in Page Edit Mode

I work on a cool project where AngularJS is used for rendering of business data in a SharePoint portal. One of the beautiful parts of AngularJS is the client validation. AngularJS understands the new html5 attributes like “required” and pattern, which makes the markup and javascript concise and semantic.

Recently I ran into a problem: The SharePoint webparts which had html forms with required fields were impossible to add to a page in the web browser, neither was it possible to edit the pages with these webparts. When I clicked on “Save”, the page tried to validate and failed.

The solution for this is very elegant, like much of the AngularJS. If you don’t show your angular form, it won’t validate. So just use any method to detect the edit mode on a SharePoint page. I created a helper function for that.

function isEditMode() {
    var publishingEdit = window.g_disableCheckoutInEditMode,
		form = document.forms[MSOWebPartPageFormName],
		input = form.MSOLayout_InDesignMode || form._wikiPageMode;	
	return !!(publishingEdit || (input && input.value));
}

In the angular controller, just define the part of it which shouldn’t be there when you are editing a page, by using ng-hide="editMode":

<div ng-contoller="PhoneCallCtrl">
   <ng-form ng-hide="editMode">
      <input type="text" required>
   </ng-form>
</div>

editMode is a $scope variable in your controller. So the last thing to do is to get the editMode value by invoking the previously defined isEditMode function:

function PhoneCallCtrl($scope, $http) {
	$scope.editMode = isEditMode();
}

Ajax and editMode

Another usage of this approach could be preventing of ajax calls when the page is being edited. There is already an example of this idea (calling ajax only in a view mode) in the standard SharePoint 2013. When you edit a page which has a Microfeed webpart. It won’t get any data until you save the page and switch to the normal page mode.

The original Visual Web Part template is missing in Visual Studio 2012

Today I encountered a weird issue, the classic Visual Web Part template was gone in Visual Studio 2012. When I created a Visual WebPart, a webpart was created with a generated .g.cs file, like the sandboxed visual webparts. I am not exactly sure why it happened. According to the MSDN guide Creating Web Parts for SharePoint, the structure of Visual Webparts should be the same as in Visual Studio 2010. It could have happened after I installed the power tools.

However, if someone runs into the same issue, here is the solution:

Copy this zip file from a computer with VS2010 installed:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\SharePoint\SharePoint14\1033\SharePoint14VisualWebPart.zip

Unpack it.

Edit SharePointVisualWebPart.vstemplate. Change the assembly line so it references to the Version 11:

<Assembly>Microsoft.VisualStudio.SharePoint.ProjectExtensions.Wizards, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>

After that copy the directory SharePoint14VisualWebPart to these two locations on your computer with Visual Studio 2012 installed.

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplates\CSharp\SharePoint\SharePoint14\1033\
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplatesCache\CSharp\SharePoint\SharePoint14\1033\

Just to be safe, save the SharePoint14VisualWebPart (which have the same name) by appending “.bak” to the name.

If you don’t have an access to a VS2010 computer, I have saved the template for you on github.

Multiple instances of javascript webparts on the same page

Javascript has become popular among many SharePoint developers thanks to easy and fast jQuery, CSOM, SPServices and many other javascript libraries.  That can make solutions modern and fast. On the other hand developers should be aware of more things (some of them at Bamboo Team Blog). One of those is scoping of javascript webparts. The problem a developer has to consider: what happens if a user creates two or more instances of the same beautiful webpart on the page?

Let’s go and lab 🙂

I’ll create a solution for this lab: sp-lend-id.ikkelen. This time it will be a sandboxed solution.

This solution contains a webpart:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="Ikkelen.ascx.cs" Inherits="sp_lend_id.ikkelen.Ikkelen.Ikkelen" %>
<link rel="stylesheet" href="/sp-lend-id/ikkelen.css"/>
<script type="text/javascript" 
    src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" 
    src="/sp-lend-id/ikkelen.js"></script>
<div id="notification-area"></div>
<input type="button" id="clickMe" value="Click me to show a notification"/>

a javascript file:

function notifyIkkelen() {
    jQuery("#notification-area")
        .append(jQuery("<div class='notification'>Tada!</div>"));
}
function initIkkelen() {
    jQuery("#clickMe").on({
        click: notifyIkkelen
    });
}
jQuery(document).on({
    ready: initIkkelen
});

And a css file for notifications inpired from twitter bootstrap alerts:

.notification {
    font-size: 20px;
    padding: 8px 35px 8px 14px;
    margin-bottom: 18px;
    color: #C09853;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
    background-color: #FCF8E3;
    border: 1px solid #FBEED5;
    border-radius: 4px;
}

Well let’s add to a page:

It works just fine. Now it’s time to add another one:

Well, this doesn’t work as it is excepted. When you click on the first button, it creates two notifications, when you click on the second button (which has the same id), nothing happens.

What shall we do about it?

Proposition 1: Make advantage of ASP.NET built-in id genereation

If you want to use your ids and make sure they don’t conflict, just add runat=”server” to your divs and in jQuery selector use ClientID:

That generates unique ids. But unfortunately it isn’t enough:

Now every time I click on the first button or the second button a notification is added to the second notification area (with the last loaded auto-generated id).

Allright, what if we “scope” it by using an anonymous function as a click event listener which won’t be overwritten:

function initIkkelen() {
    jQuery("#<%= clickMe.ClientID %>").on({
        click: function() {
            jQuery("#<%= notificationArea.ClientID %>")
                .append(jQuery("<div class='notification'>Tada!</div>"));
            }
    });
}
jQuery(document).on({
    ready: initIkkelen
});

And it works:

Okay, it works, but it sucks. You must use anonymous functions, you must put your javascript directly into markup, you must user runat=server which will generate other junk along your ids. It must be another way. We start over. Put the javascript code back to ikkelen.js, remove runat=server and ClientID.

Proposition 2. Use webpart scopes

First of all we have to remove all ids, because ids cannot be used more than once on a page. We can use just class attributes as in many projects. But there can be problems as well, because class attributes are a designer’s domain. Your solution should not break if you as designer then add and remove classes to adjust the look. Let’s take inspiration from jQuery Mobile and data-role attributes.
Ikkelen.ascx:

<div data-role="notification-area"></div>
<input type="button" data-role="clickMe" value="Click me to show a notification"/>

ikkelen.js:

function notifyIkkelen() {
    jQuery("[data-role='notification-area']")
        .append(jQuery("<div class='notification'>Tada!</div>"));
}

function initIkkelen() {
    jQuery("[data-role='clickMe']").on({
        click: notifyIkkelen
    });
}

$(document).on({
    ready: initIkkelen
});

Well, id problem is solved, but the events are fired four times:

Here when I click every button, four notification are added.

Now we must find out how we can limit our javascript and especially jQuery selectors to only one webpart. First of all we close our javascript code to a module:

(function($) {
    function notifyIkkelen() {
        $("[data-role='notification-area']")
            .append($("<div class='notification'>Tada!</div>"));
    }

    function initIkkelen() {
        $("[data-role='clickMe']").on({
            click: notifyIkkelen
        });
    }

    $(document).on({
        ready: initIkkelen
    });
})(jQuery);

The next question is what we can use to define a webpart scope. Let’s try to get current webpart id by using this.ClientID and put the id into our module, so it’s time to rewrite the module:

function ikkelen($, webpartId) {
    var webpart;
    function notifyIkkelen() {
        webpart.find("[data-role='notification-area']")
            .append($("<div class='notification'>Tada!</div>"));
    }

    function initIkkelen() {
        webpart = $("#" + webpartId);
        webpart.find("[data-role='clickMe']").on({
            click: notifyIkkelen
        });
    }

    $(document).on({
        ready: initIkkelen
    });
}

In this module which will be invoked in every instance of our webpart we create a jQuery reference to webpart (document ready). and traverse html elements only inside a webpart, by using jQuery find function.

So when we put the current webpart id into our ikkelen function along with jQuery reference:

<script type="text/javascript">
    ikkelen(jQuery, "<%= this.ClientID %>");
</script>

It works as expected:

Now a new notification is added in the webpart in which I click on the button.

Do you have other ideas about this topic? Let me know!

As I said, check out the code in my github repository:  sp-lend-id.ikkelen.

UPDATE.

If the webpart is  the classical visual webpart (farm solution, with a user control), use Parent instead of this:

(jQuery, "<%= this.Parent.ClientID %>")

Develop for SharePoint on Windows 8

Do you like Windows 8 user expirience, as me? Well than you want to try developing sharepoint solutions in Windows 8. Here I will show what I found out.

Environment

I installed Windows 8 Release Preview as a VMWare machine. Then I installed Visual Studio 2012 RC. Then I followed the steps for installing SharePoint on Windows 8 which are more or less the same as for Windows 7 client install. But then I encountered an error I haven’t found solution for yet. In my standalone sharepoint installation there were some permission problems:

Failed to create the configuration database.

An exception of type System.Data.SqlClient.SqlException was thrown. Additional information:
Cannot find the object ‘proc_putDeletedSiteMap’,because it does not exist or you do not have permission.

Plan B

In a meanwhile I tried to just to use Andrew Connell’s trick: to copy sharepoint dlls to GAC and the 14 folder. To extract the sharepoint dlls, you can use a script from sharepoint tech blog:

mkdir c:\temp
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Portal")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Policy")
[appdomain]::currentdomain.getassemblies() |
where {($_.fullname -match "Microsoft.Office") -OR ($_.fullname –match "Microsoft.SharePoint")} |
copy-item -path {$_.location} -destination c:\temp\ -verbose

Then copy the dlls to gac with gacutil.

This plan B works, but with one shortcoming: you can’t debug, neither you can create new sharepoint solutions, you’ll get an error: “SharePoint Not Installed”.

What you have to do is to open an existing sharepoint solution. And you can build it and publish. After I opened an existing solution in Windows 8, I could create new solutions as well :).

The most awesome feature in Visual Studio 2012 is the ability to publish your projects:

Enable cookies in Page Viewer WP

Вула Чăвашла

VulaCV - Чăвашла вулаттаракан сайт

Discovering SharePoint

And going crazy doing it

Bram de Jager talking Office 365, SharePoint and Azure

My view and thoughts on Productivity and more.

My programming life

and everything in between

SharePoint Development Lab by @avishnyakov

It is a good place to share some SharePoint stories and development practices.

SharePoint Dragons

Nikander & Margriet on SharePoint

RealActivity - Real-time and trustworthy

Blog site of founder, RealActivty - Paul J. Swider

Mai Omar Desouki - Avid SharePointer

Egyptian & Vodafoner - Senior SharePoint Consultant

Cameron Dwyer | Office 365, SharePoint, Outlook, OnePlace Solutions

Office 365, SharePoint, OnePlace Solutions & Life's Other Little Wonders

paul.tavares

Me and My doings!

Share SharePoint Points!!

By Mohit Vashishtha

Jimmy Janlén "Den Scrummande Konsulten"

Erfarenheter, synpunkter och raljerande om Scrum från Jimmy Janlén

SPJoel

SharePoint for everyone

SharePointRyan

Ryan Dennis is a SharePoint Solution Architect with a passion for SharePoint and PowerShell

SharePoint 2020

The Vision for a Future of Clarity

Aharoni in Unicode, ya mama

Treacle tarts for great justice

... And All That JS

JavaScript, Web Apps and SharePoint