Create basic SharePoint Add In using Angular 2

My last post concerns mainly to create a simple angular 2 application.

Now that we are well versed with it, our focus shifts as to how Angular 2 can be integrated with SharePoint. Let’s take a look into this one now.

Setting up the project for creating SharePoint Add In using Angular 2 in Visual Studio is quite confusing, hence I’m writing a detailed step by step description.

Also, point to be considered is, we will develop a SharePoint hosted Add In targeted for SharePoint 2013. The same may work for SharePoint Online, though I haven’t tried to explore it.

Creating Add In and removing unwanted files

Create a SharePoint Add In project in Visual Studio to be hosted as a SharePoint App targeted for SharePoint 2013.

The solution explorer has following files
setup1.jpg

Go to “Manage NuGet Package” and under the installed packages, remove the jQuery library.

This will remove all jQuery scripts from the Scripts folder.

setup2.jpg

Now, the Scripts folder should look like belowsetup3.jpg

Delete the app.js file from the Scripts folder.
setup4.jpg

tsconfig.json –

Add new item and search for the template json. Add the file – tsconfig.json

setup5.jpg

Add the below code to the file

{
  "compileOnSave": true,
  "compilerOptions": {
    "watch": true,
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "outDir": "./Scripts"
  },
  "exclude": [
    "node_modules"
  ]
}

Go to properties of tsconfig.json (F4)

Set Deployment type to NoDeployment

setup6.jpg

Other supporting libraries

Run the command prompt as administrator and traverse to the project folder.

Run the command – npm install angular2 systemjs es6-promise es6-shim rxjs

setup7.jpg

All packages will be placed under a folder named node_modules

The folder won’t be available in the solution explorer, however, upon clicking “View All Files”, the folder can be seen that is excluded from the project. Try not to include it as it will crash the VS.

setup1.jpg

To note – In a plain Angular2 app, the command used is npm install. It will generate all the libraries and place it inside the node_modules folder. However, this won’t work in a SharePoint Add In and may generate an empty folder. Hence, use the above mentioned command.

package.json – Having added the required libraries, let us move on to add this file – package.json.

  • Run command prompt as administrator
  • Traverse to the project folder
  • Run the command – “npm init”
    • The command prompt will ask few questions like the name, version, description, author, license, etc. Let all default values persist by just entering a name in lower case and entering blank for other values.
    • Confirm with a yes after furnishing all values.

setup1.jpg

A package.json file is created in the project, which is invisible in the solution explorer.

The same could have been created by the command – “npm init -y“. This would ensure that you don’t have to enter any default values and the package.json is created for you. However, once created, the name has to be changed to lower case, else it will show the red squiggly for error.

Show all files in solution explorer and right click on “Package.json”. Include it in project.

setup1.jpg

Go to properties of package.json (F4)

Set Deployment type to NoDeployment

setup1.jpg

App folder

  • Add a folder – app to the project
  • Add the component file
      • Add new item in the app folder
      • Search for the template TypeScript and create a file by the name – app.component.ts

setup1.jpg

  • import { Component } from 'angular2/core';
    @Component({
        selector: 'my-app',
        template: '
    <h1>My First SharePoint Add In using Angular2... Yoohoo!!!</h1>
    '
    })
    export class AppComponent { }
    

Write the above code and save the file. Saving the ts file generates a js file in the “Scripts” folder which won’t be visible.

Refresh the solution explorer and click “Show all files”, the js file will be visible in Scripts folder.

 

Before saving app.component.ts After saving app.component.ts
 setup1.jpg  setup1.jpg

Right click the js file in the Scripts folder and include in project.

Go to properties of app.component.ts (F4)

Set Deployment type to NoDeployment

  • Add the main/boot file

Add new typescript file in the app folder by the name – main.ts

import { bootstrap }    from 'angular2/platform/browser';

import { AppComponent } from './app.component';

bootstrap(AppComponent);

Write the above code and save the file. Saving the ts file generates a js file in the “Scripts” folder which won’t be visible.

Refresh the solution explorer and click “Show all files”, the js file will be visible in Scripts folder

Right click the js file in the Scripts folder and include it in project

Go to properties of main.ts (F4)

Set Deployment type to NoDeployment

So now, the solution explorer will look like

setup1

Note: You may encounter the following error while saving the ts files – “Project contained error. Output generation skipped”. However, the js files are generated, hence this error can be ignored.

Dependent Scripts

Add a new folder called NodeScripts to the project

Go to the below links right click and save each of the js files

Add these js files to the NodeScripts folder in the project

setup1.jpg

Web Page to host the application

Go to default.aspx page under Pages folder

Under PlaceHolderAdditionalPageHead, put the below content

<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">

    <meta name="WebPartPageExpansion" content="full" />

        <script src="../NodeScripts//es6-shim.min.js"></script>
        <script src="../NodeScripts/system-polyfills.js"></script>
        <script src="../NodeScripts/angular2-polyfills.js"></script>
        <script src="../NodeScripts/system.js"></script>
        <script src="../NodeScripts/Rx.js"></script>
        <script src="../NodeScripts/angular2.dev.js"></script>

        <script>
            System.config({
                packages: {
                    '../Scripts': {
                        format: 'register',
                        defaultExtension: 'js'
                    }
                }
            });
            System.import('../Scripts/main')
                  .then(null, console.error.bind(console));
        </script>
    </asp:Content>

Significance of above code

  • Shim and Pollyfills are used to support ECMA 6
  • System.js is used for
    • Using modules in JavaScript so that your JS doesn’t collide with others. Compartmentalize!
    • Load modules as they are needed and not all at once
  • Rx.js – Reactive extension to have “Promises” from JS for asynchronous calls.
  • Angular 2 library
  • System.config is used
    • To tell where the loader can find the scripts (here inside the Scripts folder)
    • To use scripts with extension “js”
  • System.import mentions the first file that is required to start the application. (here the file is main inside Scripts folder). It is equivalent to the main method.

Under PlaceHolderMain, put the selector

<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">

    <my-app></my-app>

</asp:Content>

Save the page

Now, the development is complete with all components and a let us do a quick check to ensure we are ready for deployment.

The deployment type is set to “NoDeployment for

  • all typescript files (.ts files inside app folder)
  • package.json and tsconfig.json

The js files for the respective ts files inside the Scripts folder are included in project.

Clean the solution and deploy

Opening the app will display the view that is created using Angular2.

setup1.jpg

Further typescript files can be added for any kind of logic and the respective JavaScript files can be deployed.

Advertisements

SharePoint event receiver getting triggered multiple times

Problem – Event receiver is getting fired twice.

My event receiver was supposed to send email to creator upon item added event. The event receiver was triggered, though it was sending two emails every time an item was created.

This was an indication that there were two event receivers attached to my list.

Solution – I followed the  below steps to troubleshoot

Continue reading

system.security.authentication.authenticationexception: the remote certificate is invalid according to the validation procedure.

Problem statement – While sending email using SMTP client using C# code, the following error comes up

system.security.authentication.authenticationexception: the remote certificate is invalid according to the validation procedure.

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel

Solution – Add the code before calling smtpClient.Send(mail)

//Add following namespaces
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

smtpClient.EnableSsl = true;

ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

Retrieve email id from a person or group field programatically

Requirement –  To retrieve email id of a user from a person or group field of a SharePoint list or library using C# code

Solution – Assuming that the query returns a list item collection

SPListItemCollection itemCollConfig = oConfigList.GetItems(oQuery);

if (itemCollConfig.Count &gt; 0)
{
     SPFieldUser userField = (SPFieldUser)itemCollConfig.Fields.GetField("HOD");
     //strHODEmail = Convert.ToString(itemCollConfig[0]["HOD"]);
     SPFieldUserValue userFieldValue = (SPFieldUserValue)userField.GetFieldValue(itemCollConfig[0]["HOD"].ToString());

      SPUser user = userFieldValue.User;
      strHODEmail = user.Email;
 }

First a reference is established to the field (field name – HOD in my case), and then the user value is retrieved from the particular index for that field.

Now remember, this would work when the person or group field is configured to accept only one value at a time.

If multiple users can be selected, then the class would vary slightly and collection will be used. Assuming item reference is available

string stEmails = string.empty;
SPFieldUser userField = (SPFieldUser)item.Fields.GetField("Users");
SPFieldUserValueCollection userFieldValueCollection = (SPFieldUserValueCollection)userField.GetFieldValue(item["Users"].ToString());
foreach (SPFieldUserValue userFieldValue in userFieldValueCollection)
{
strEmails = strEmails + userFieldValue.User.Email;
}

 

Next situation – When it is a people editor control on the page/web part, how to retrieve the user’s email. Below code would facilitate for the same. The people editor control here is “pplSendMail”

string strEmail = string.Empty;              
if (pplSendMail.ResolvedEntities.Count > 0)
{
    for (int i = 0; i < pplSendMail.ResolvedEntities.Count; i++)
    {
        PickerEntity user = (PickerEntity)pplSendMail.ResolvedEntities[i];
        SPUser webUser = SPContext.Current.Web.EnsureUser(user.Key);
        SPFieldUserValue value = new SPFieldUserValue(SPContext.Current.Web, webUser.ID, webUser.Name);
        strEmail = strEmail + "," + webUser.Email;
    }
}

Regex to validate email ids in InfoPath

Requirement – InfoPath form’s column should allow multiple valid email ids to be keyed in, separated by a comma.

InfoPath allows validation of an email id by default. It has a pattern to compare to. However, when the need arises to have multiple email ids inserted in a column, how to validate if all are valid email ids and are separated by a comma?

Solution – Write a validation rule for the column. The condition would be

Field: Email

Condition: does not match pattern

Custom pattern:  ([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\s*,\s*([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3}))*

Email

Send emails to distribution lists using SharePoint

It is easy to send emails to shared mailboxes or to distribution lists (DL) using your outlook. But have you ever wondered what happens when you try sending email to a DL using SharePoint (workflow).

I had the requirement to send emails to multiple DLs using my workflow and a 2 hours estimated work took me nearly 2 days to complete.

Basically, the email id of the DL won’t appear in your active directory while you search for it. Also, it is fair enough since a DL has no physical mailbox associated to it, just an id. Hence, the email id of the DL won’t be resolved.

Solution – Email enabled security group!!

In order to send emails to a DL from SharePoint, the DL needs to be converted to a security group that is email enabled. The same setting can be done by the exchange engineer either through command prompt or through exchange console. Below steps can be followed

  1. Go to Exchange Management Console -> Recipient Configuration -> Distribution group.
  2. Right-click on the problem group (i.e. the DL or the security group) and choose properties.
  3. On the Mail Flow Settings tab, double click on Message Delivery Restrictions.
  4. Uncheck the check box “Require that all senders are authenticated”.

 

Once done, the DL’s id can easily be searched in SharePoint’s directory and emails can be sent using workflows. However one thing to be kept in mind, it is the description or the display name that can be searched and not the DL’s email id directly.

Hope this helps!

 

 

Publishing a Nintex workflow to lists & libraries in multiple sites

My previous post was how can a Nintex workflow be published to multiple lists in the same site.
This time, it is a slight variation. The question this time is how can a workflow be published to multiple lists that reside on different sites.

Interesting stuff!! Trust me 🙂

Let me tell you how I came to this scenario

Requirement
I have a site that is saved as a template, and close to 200+ sites have been created out of that template. All worked great until one day when I received this request for a change in one of my workflows in one of the lists of the site.

Also, this change had to be copied to almost 40 out of the 200 sites created.

Of course, I made the changes in the template site, but the challenge was how do I publish my updated workflow to the said sites.

This happened to be a slight extension to the same methodology that was used previously. Continue reading

Publishing a workflow to multiple lists and libraries (in same site!)

Requirement – I have a site that has around 40 country lists which have the same workflow. When there is a change in the workflow, there is a need to update the workflow in all 40 lists; which is practically impossible. Also, it wouldn’t be considered a good practice.

As most of the times, I knew there was a solution using Nintex. And the  moment I found it, I fell even more in love with this workflow tool. It keeps surprising me as always!

Solution – Nintex workflow comes with a web method called PublishFromNWFXML that will do this job for us.
Update your workflow at the parent location and export it. Upload the nwf file to a library (here – Shared Documents) and create the below workflow on this library, that will update it to the multiple lists.

Continue reading

Remove html tags from SharePoint list’s display form

Many a times, specially for look up columns in a SharePoint list, the display form returns html tags instead of the value.

For instance, below image has a look up field called Office, that shows the complete anchor tag instead of the value.

Post33

This happens while assigning the xsl value to a field in the display form. The optional attribute called “disable-output-escaping” plays the key role here. If it is set to ‘no’ (which is by default), special characters (like ‘<‘) will be output as ‘&lt;’. And if it set to ‘yes’, it means that special characters (like ‘<‘) should be output as is.

Hence, to implement this, open the display form in SharePoint designer and add this attribute i.e. disable-output-escaping=”yes” to the <xsl> tag.
For above example, the solution would be

<tr>
    <td width="190px" valign="top" class="ms-formlabel">
	<H3 class="ms-standardheader">
	     <nobr>Office</nobr>
	</H3>
    </td>
    <td width="400px" valign="top" class="ms-formbody">
	<xsl:value-of select="@Office" disable-output-escaping="yes"/>
    </td>
</tr>

Change default font of a rich text box in SharePoint

Requirement – To change the default font – style of the rich text box
The multiple lines of text field, when selected as rich text or enhanced rich text has an advantage of styling the content inside at the run time, which is actually very helpful.

But then I ran into the situation where the user asked me to change the default font-style and font-size. They didn’t wanted to go through the process of changing the styles every-time a user fills in the rich text box. Also, this was to ply with the organization’s standard styles.

So, the solution is to write css.

The default style is defined in the core.css file. Hence, to change the default values, either a new css can be created or the style can be written in a content editor web part of the new form. The class for the rich text box is .ms-rtestate-write.

Below is the css to style the rich text box.

<style type="text/css">
   .ms-rtestate-write 
   {
       FONT-FAMILY: Calibri; 
       COLOR: grey; 
       FONT-SIZE: 11pt
   }
</style>