Categories
SharePoint 2013

Vuetify Expansion Panel in SharePoint

I have had the pleasure of doing a lot with the VUE.js framework and I have created tons of videos on using Vue.js with SharePoint. I recently created a video on using Vuetify with SharePoint. Vuetify is a ‘Material Design Component Framework’ made for VUE. Check out the UI components. There are a plethora of components that can be leveraged and used in SharePoint. Here’s a video on using the ‘Expansion Panel‘ I created recently. Below is the code used in the video:

<head>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.14/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify@1.5.14/dist/vuetify.min.css" />
</head>
<body>
<div id="app">
<v-app id="inspire">
<v-expansion-panel inset focusable>
<v-expansion-panel-content lazy
v-for="(item,i) in expansion"
:key="i"
>
<template v-slot:header>
<div>{{item.Title}}</div>
</template>
<v-card>
<v-card-text>{{item.Details}}</v-card-text>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</v-app>
</div>
<script type="text/javascript" src="/sites/demos/mdemos/webpart/expansion/expansionPanel.js"></script>
view raw expansion.html hosted with ❤ by GitHub
new Vue({
el:"#app",
data: {
expansion: []
},
created: function(){
this.getListData();
},
methods: {
getListData: function(){
var endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbyTitle('expansion list')/items";
var vm = this;
axios.get(endPointUrl).then(function(response){
vm.expansion = response.data.value;
})
.catch(function(error){
console.log(error);
})
.then(function(){
console.log("Always executes")
})
}
}
})
view raw expansion.js hosted with ❤ by GitHub
Categories
SharePoint

Retrieve id after REST API Insert

Today I needed to use REST API to insert data into a list and I also needed to retrieve the id of the new inserted item. The code below successfully inserted my data into the list but the success handler wasn’t firing.

$.ajax({
	url: fullUrl,
	type: "POST",
	data: JSON.stringify({
		'__metadata': { 'type': 'SP.Data.Travel_x0020_RequestListItem' },
		'Guidance1': guidance1,
		'Guidance2': guidance2,
		'Guidance3': guidance3
		}),
	headers: {
		"accept": "application/json;odata=verbose",
		"content-type": "application/json;odata=verbose",
		"X-RequestDigest": $("#__REQUESTDIGEST").val()
	},
	success: function(data){
		alert("Retried id of new inserted item"+data.d.Id);
		console.log(data.d.Id);
	},
	error: function(data){
		alert("Epic fail");
	}
});
}

After a bit of googling and being on SharePoint stack exchange, it was suggested that I change “type” to “method”. Once I did that, it worked.

$.ajax({
	url: fullUrl,
	method: "POST",
	data: JSON.stringify({

I hope this helps someone.

Categories
NINTEX SharePoint SharePoint 2013

Nintex – Assign Flexi Task

I have heard so many good things about NINTEX that I was excited when I finally had the chance to use it in place of SharePoint designer.  My task was to create a document approval workflow.  Here’s a diagram showing the process.

User uploads document  –> Notificaion sent to Chief –> Chief approves, disapproves –> Notification sent to AD –> AD approves, disapproves –> Notification sent to ED –> ED approves, disapproves

Creating the above process with Nintex was not a problem.  The problem was creating a reminder email to be sent.  When a notification is initially sent, the recipient will have two days to review the document and approve.  If the recipient hasn’t taken any action after two days, another notification should be sent.  I struggled with this for a few days googling (lots of different solutions) but was finally able to resolve this issue, thanks to a colleague.  He recommended using ‘flexi-task’ which worked great.  See images below.

With Nintex workflow open, select Assign Flexi task

AssignFlexiTaskIcon

Once you have dragged it to the workflow canvas, click the chevron next to the Assign Flexi task and select Configure from the list of options.

flexiTaskConfigure

When the configuration settings open up, in the Action tab add the Assignees name.

flexiTaskAction

Click on the Task Notification icon button and add any CC or BC and any message you want to be read on the initial email when a task is assigned.

flexiTaskNotification

Then click on the Reminders icon.  Add how many reminders you want to send out, 1 in my case.  Add the number of days between reminders, 2 for me.

flexiTaskReminder

Click Save and that’s it.

Hope this helps.

Thanks and please leave a comment and/or feedback below.

Categories
SharePoint SharePoint 2013

DOM still applies in SharePoint

There’s so much to remember when dealing with the DOM, especially when in SharePoint.  I am writing this post so I don’t forget and go searching “again”.  Here’s the scenario,  I needed to get data from a list and populate an html dashboard that will be rendered to a SharePoint page.  I use REST API and jQuery AJAX to retrieve my data so I can place it in the right place.  Below is my initial code and the error I was receiving.

    var endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbyTitle('dashboard')/items";

    var fieldStaff=document.querySelector("#fieldStaff");    

$.ajax({
    url: endPointUrl,
    type: "GET",
    headers: {
    "accept": "application/json;odata=verbose"
},
}).success(function (data) {
               fieldStaff.appendChild(data.d.results[0].FieldStaff);
});

The code produced the following error:
Uncaught TypeError: Failed to execute ‘appendChild’ on ‘Node’: parameter 1 is not of type ‘Node’.

It’s complaining that the parameter, data.d.results[0].FieldStaff is not a node, which means I need to make it a node.  But how?  After a little digging, I remembered that every HTML webpage gets parsed into a tree like structure of node objects and everything becomes a node(elements, text, etc.), so the value of data.d.results[0].FieldStaff must be a node.  The code below shows how I turned it into a node using the DOM API document.createTextNode().

    var endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbyTitle('dashboard')/items";
var fieldStaff=document.querySelector("#fieldStaff");    

$.ajax({
    url: endPointUrl,
    type: "GET",
    headers: {
    "accept": "application/json;odata=verbose"
},
}).success(function (data) {
      /*Make returned data a DOM Node*/
     var fieldStaffTextNode = document.createTextNode(data.d.results[0].FieldStaff);
     fieldStaff.appendChild(fieldStaffTextNode);

});

Error gone!

Thanks for reading!  Happy coding.

Categories
SharePoint

JSOM: Update Item

While trying to update an item in a SharePoint 2013 list, something I’ve done many times before, I received the following error:

Error: “SCRIPT5007: Unable to get property ‘apply’ of undefined or null reference. File: ScriptResource.axd, Line 5, Column: 298”

Here’s the code that generated that error:

var siteUrl = _spPageContextInfo.webAbsoluteUrl
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle('Document Approval');
var oListItem = oList.getItemById(promise.responseJSON.d.results[0].ID);

oListItem.set_item('Role Status', roleStatus);
oListItem.update();

clientContext.executeQueryAsync(
 Function.createDelegate(this, this.onAddSucceeded),
 Function.createDelegate(this, this.onAddFailed)
);

function onAddSucceeded(sender, args){
  console.log("Item successfully updated!");
}

function onAddFailed(sender, args){
  console.log("Request Failed");
}

The problem was in the way I was referencing the functions (onAddSucceeded and onAddFailed). Using the ‘this’ keyword means that both onAddSucceeded and onAddFailed are part of the object which they aren’t. So the following modification worked, thanks to SharePoint stackexchange.

var siteUrl = _spPageContextInfo.webAbsoluteUrl
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle('Document Approval');
var oListItem = oList.getItemById(promise.responseJSON.d.results[0].ID);

oListItem.set_item('Role Status', roleStatus);
oListItem.update();

clientContext.executeQueryAsync(
 onAddSucceeded,onAddFailed
);

function onAddSucceeded(sender, args){
  console.log("Item successfully updated!");
}

function onAddFailed(sender, args){
  console.log("Request Failed");
}

Hope that makes sense. Love to hear from you.

Categories
SharePoint

Getting SharePoint radio button value from the DOM

I was stumped the other day with something that I thought would be easy.  I had a form and on the form a radio button with three options.  All I wanted to do was grab the value and I was having a hard time doing so.  I was able use the code below to do so.

var btn =  document.querySelector("input[name^='ctl00$ctl40$g']:checked").value

Note: the value returned is not the actual value you want but the value generated by SharePoint such as ‘ct100’, ‘ct101’, etc.

What you have to do is associate each of the generated values with your actual values and use a condition to test and take the appropriate action.  For example, if ‘ct100’ represent ‘Vanila’, you could do something such as the below.

    if (btn=='Vanila'){
      /*Do Something*/
    }

Hope this was helpful. If you have another method, please share.

Thanks and happy coding! 🙂

Categories
SharePoint

get_current or undefined error (JSOM)

Recently, I created a custom survey form with JSOM (JavaScript Object Model) as my choice for inserting data into a SharePoint list form.  It worked perfectly on my test site but when I moved it to our live SharePoint site, I received the following error.
**Uncaught TypeError: Cannot read property ‘get_current’ of undefined**

  var ctx = new SP.ClientContext.get_current(); //**<--ERROR HERE**
        var cList = ctx.get_web().get_lists().getByTitle('2018Survey');

        var itemCreateInfo = new SP.ListItemCreationInformation();
        var listItem = cList.addItem(itemCreateInfo);
        listItem.set_item('CurrentSharePointRole', this._qs("#CurrentSharePointRole").value);
        listItem.set_item('SharePointYammerUseful', this._qs("#SharePointYammerUseful").value);
        listItem.set_item('SharePointYammerUsefulWHY', (this._qs("#SharePointYammerUsefulWHY").value) ? this._qs("#SharePointYammerUsefulWHY").value : "N/A");
        listItem.set_item('AttendedBrownBag', this._qs("#AttendedBrownBag").value);

The site that I moved my code to was heavily customized and it was a publishing site.  I’m not sure if it was the customization or the publishing feature that made my JSOM code to break but after much digging and debugging, I added the following libraries to my html and it worked perfectly.

/_layouts/sp.core.js
/_layouts/sp.runtime.js
/_layouts/sp.js

I hope this helps someone.  Thanks and please leave a comment if you find this helpful or insightful. Also, you are welcome to provide any feedback.  I can take it.  🙂

Categories
SharePoint SharePoint 2013

Add functionality to SharePoint form using DOM API

Recently I was faced with the need to add validation to a SharePoint list form.  Our environment was SharePoint 2013 on-prem so our only option was InfoPath and I refused to go down that road.  So I reverted back to what any developer would do.  I used plain old vanilla JavaScript and DOM development.  Here’s the scenario:

I had a SharePoint list that had 4 content types with different fields and each content type needed to have certain fields hidden as it went through a document approval process.  Here’s an image of what one of the 4 content type approval forms looks like.  In this blog, I will show you how to use DOM traversal to add functionality to a form.

approvalWorkflow.png

In the above form, Chief Document Approve? has the following options in the drop down (Approval, Approval with Feedback, Final Approval, Further Discussion Needed).  The functionality that needed to happen was that if Approval with Feedback or Further Discussion Needed was selected, then Chief Feedback multi-line box would show, if not it will be hidden.

When a new form is initially opened, the Chief Document Approve? drop down would be blank, which means that the Chief Feedback multi-line box would need to be hidden by default.   I will show you how to accomplish this but first, here’s what the DOM of Chief Feedback looks like.  As you can see in the image below, the textarea’s (Chief Feedback) parent is the span tag which is inside of a td tag which is inside of a tr tag.  So the textarea tag has three parents as seen below.

domElement

Now that we know what the DOM looks like, we can use this new reference to hide the Chief Feedback box.  See code below.


var chiefFeedback = document.querySelector("[title='Chief Feedback']");
chiefFeedback.parentNode.parentNode.parentNode.style.visibility = "hidden"; 

As you can see from the first line, we get a reference to our textarea box by referencing it by its title using the querySelector DOM API.  Once we have that reference, we reference the whole row (tr) by traversing all the way up to the parent from the textarea box.  That’s why we have the three parentNode from chiefFeedback.  Once we have that we use style.visibility = ‘hidden’ to hide the whole row.  But that’s only half the battle.  We want the feedback box to show if the drop down selection is Approval with Feedback or Further Discussion Needed and be hidden if not selected.

What we would need to do to accomplish our next task is to attach an onchange event to the drop down so that when there is a selection, we can check for what it is and take the appropriate action.   See code below on how to accomplish this.  There’s enough comments to understand what’s going on.

   /*Get a reference to the chief approve drop down box*/
   var chiefApprove = document.querySelector("[id^='ChiefDocumentApproval']");

   /*Attach an onchage event to drop down*/
   chiefApprove.onchange = function(){

   /*Grab the selected value*/
   var aValue = chiefApprove.options[chiefApprove.selectedIndex].value;

   /*Show and hide feedback field based on the selected value*/
   if(aValue == "Approval with Feedback" || aValue == "Further discussion needed")
     {

     /*Show box*/
     chiefFeedback.parentNode.parentNode.parentNode.style.visibility = "table-row";
     }else{

    /*Hide box*/
    chiefFeedback.parentNode.parentNode.parentNode.style.visibility = "hidden";
     }

   }

I hope this makes sense and can help you.  Happy SharePoint Client Side Coding! 🙂  Please leave a comment if you like this post.

Categories
SharePoint

Using Vuejs in SharePoint

In the past few weeks, I have been fascinated with how easy VUE.js is to learn and to use.  Not only is it easy to use but it easily integrates with SharePoint.  For those of you not familiar with VUEJS, it is a JavaScript framework that makes development much fun and efficient.  Out of all the frameworks (angular, react, etc), I found vuejs to be straightforward without the complexities of a lot of frameworks.

In this blog post, I will show you how to do something very simple, which is to render SharePoint list data onto a page using VUEJS.  But first, lets understand the foundation of how VUEJS works.  First, you must have a reference to the vue library in your page, like so

vue

To start, we will create an instance of VUE. “Every Vue application starts by creating a new Vue instance with the Vue function.” For us to link data to our view, we must add properties to our data object. The data property will contain the data that will be displayed in our html, in this case message.  There are many types of properties we can add to our vue instance such as “method”, “created”, but we will go over that later and probably in future blog posts.  Here’s an example of creating an instance of VUE.

Here’s a link to JSBIN with the code above https://jsbin.com/safapen/edit?html,output

Change the message in the data property of the Vue instance and watch how reactive the HTML is.

Now that we have that out of the way.  How do we get this to work in SharePoint?

I have a list called ‘siteAdmins’ with 4 columns (‘Email‘, ‘First Name‘, ‘Last Name‘, and ‘Phone‘).

Here’s the html code with explanation of what’s happening
blogVue1

In the code above, the following line loops through the ‘user’ array and builds the rows to our table as it populates the cells with data from our list.

We use the ‘v-for‘ directive to achieve the looping.

Here’s the js code with my VUE instance with some detail.
blogVue2

In the image above, I have a generateData function that’s not really doing anything. I kept it in there just to show that you can have any number of functions within the data method that you can call upon. Here’s the results showing the rendered data from my list and the effects of v-for and v-if directive.

vueBlog3

Rendering the data in an html table is just an option. You could have also used DIV’s.

Here’s the jsbin that shows the same code but the data is coming from https://jsonplaceholder.typicode.com. This site is a “REST service that you can use whenever you need some fake data.”   Here’s the fake data.

In a future blog post, I will show how to create a dataTable that’s much prettier and has functionality.

Categories
SharePoint

InfoPath: Any occurrence of…

Have you ever had to deal with the ‘Multiple-Selection List box’ in InfoPath? What a headache it can be if you are  not familiar with how to get the selected values.

I am using an infoPath 2013 form with SharePoint. I had a multiple selection list box called request with the following values “Software, Space (West Only), Workstation, Mobile Device (Region & Employees only)”. 

I created a rule on form submit with the following condition: 

Condition: Value = “Mobile Device (Region & Employees only)” 

Rule type: Action 

Run these actions:* Set a field’s value: Status = “Pending”

It basically reads, if the selected value of ‘Requesting'(shows as Value) is equal to “Mobile Device (Region & Employees only)” , set the ‘Status’ value, found in SharePoint, to “Pending”.  Well, that didn’t work and it took me a while to figure it out. Thanks to Data (That’s what I call google-Someone should create a search engine called ‘Data’ like the star trek dude), I was lead to infoPathDev site and got the help I need.

Here was the solution:

When you create your rule and are in the condition area, “Select a Field or Group” –> Choose your Multiple-Selection List field name (‘Requesting’ for me)–>”Show advanced view”–>Expand the folder and select ‘value’–>In the select drop down below, select ‘Any occurrence of Value’–>Click ‘Ok’ and ‘Ok’.

infoPathRules

It will now read, if any occurrence of ‘Requesting’ is equal to “Mobile Device (Region & Employees only)”, set the ‘Status’ in SharePoint.

Hope that helps someone.

InfoPath your way to the top. 🙂