May 9, 2022 / Kannan / 0 Comments
When writing a react based SPFx application one has to make a note that ES6 React.Component doesn’t auto bind methods to itself.
Hence it’s required to manually bind and the following are two ways to do it.
Method 1
onClick={this.addButtonClicked.bind(this)}
import * as React from 'react';
import { Stack, IStackProps, IStackStyles } from 'office-ui-fabric-react/lib/Stack';
import { ActionButton } from 'office-ui-fabric-react/lib/Button';
import { IIconProps } from 'office-ui-fabric-react/';
import { ITestComponentState } from './ITestComponentState';
import { ITestComponentProps } from './ITestComponentProps';
//Stack related styles
const outerStackTokens = {
childrenGap: 50
};
const addFriendIcon: IIconProps = { iconName: 'Add' };
let outerStackStyles: Partial<IStackStyles> = {};
let innerStackColumnProps: Partial<IStackProps> = {};
export default class TestComponent extends React.Component<ITestComponentProps, ITestComponentState> {
constructor(props: ITestComponentProps) {
super(props);
this.state = {
items: []
};
}
public render(): React.ReactElement<{}> {
return (
<div>
<Stack horizontal tokens={outerStackTokens} styles={outerStackStyles}>
<Stack verticalAlign="start" {...innerStackColumnProps}>
<Stack.Item align="start" >
<ActionButton iconProps={addFriendIcon} onClick={this.addButtonClicked.bind(this)} allowDisabledFocus disabled={this.state.sortItems.length >= 10 ? true : false} >Add Item</ActionButton>
</Stack.Item>
</Stack>
</Stack>
</div>
);
}
private addButtonClicked(event?: React.MouseEvent<HTMLButtonElement>) {
let itemsOnAdd = this.state.items;
let itemTitle = "Item " + (this.state.items.length + 1);
itemsOnAdd.push({ title: itemTitle });
this.setState({ items: itemsOnAdd });
}
}
Method 2
this.addButtonClicked = this.addButtonClicked.bind(this);
import * as React from 'react';
import { Stack, IStackProps, IStackStyles } from 'office-ui-fabric-react/lib/Stack';
import { ActionButton } from 'office-ui-fabric-react/lib/Button';
import { IIconProps } from 'office-ui-fabric-react/';
import { ITestComponentState } from './ITestComponentState';
import { ITestComponentProps } from './ITestComponentProps';
//Stack related styles
const outerStackTokens = {
childrenGap: 50
};
const addFriendIcon: IIconProps = { iconName: 'Add' };
let outerStackStyles: Partial<IStackStyles> = {};
let innerStackColumnProps: Partial<IStackProps> = {};
export default class TestComponent extends React.Component<ITestComponentProps, ITestComponentState> {
constructor(props: ITestComponentProps) {
super(props);
this.state = {
items: []
};
this.addButtonClicked = this.addButtonClicked.bind(this);
}
public render(): React.ReactElement<{}> {
return (
<div>
<Stack horizontal tokens={outerStackTokens} styles={outerStackStyles}>
<Stack verticalAlign="start" {...innerStackColumnProps}>
<Stack.Item align="start" >
<ActionButton iconProps={addFriendIcon} onClick={this.addButtonClicked} allowDisabledFocus disabled={this.state.sortItems.length >= 10 ? true : false} >Add Item</ActionButton>
</Stack.Item>
</Stack>
</Stack>
</div>
);
}
private addButtonClicked(event?: React.MouseEvent<HTMLButtonElement>) {
let itemsOnAdd = this.state.items;
let itemTitle = "Item " + (this.state.items.length + 1);
itemsOnAdd.push({ title: itemTitle });
this.setState({ items: itemsOnAdd });
}
}
April 26, 2020 / Kannan / 0 Comments
Sometimes we need to call a React function from HTML tags with parameters or arguments and following is the ES6 based way.
Here a button is calling a function updateName with argument newName to set a state which in turns changes the name being displayed.
import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'Kannan'
};
}
updateName = (newName) =>{
this.setState({
name: newName
})
}
render() {
return (
<div>
<p>My Name is {this.state.name}.</p>
<p>
<button onClick={this.updateName.bind(this,'Kannan Balasubramanian')}>Change the name</button><br/>
<button onClick={()=>this.updateName('Kannan Balasubramanian!')}>Change the name again</button>
</p>
</div>
);
}
}
render(<App />, document.getElementById('root'));
Do note that using this.updateName.bind() is the recommended way due to performance and efficiency concerns.
You can try the sample output here.
July 18, 2017 / Kannan / 0 Comments
Following code will help in fetching the value of a query string parameter.
function GetQueryStringParameter(parameter) {
var search = location.search.substring(1);
var queryStringParameters = JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}')
return queryStringParameters[parameter];
}
Usage:
If URL is http://server/page.html?id=1
Then usage would be GetQueryStringParameters(“id”) which would return 1
July 17, 2017 / Kannan / 0 Comments
The following script changes the “new item” link button in SharePoint view form to whatever we desire.
Add either of the script to content editor web part.
Plain JavaScript version: (This code assumes that there is only one “new item” text in the entire page.)
<script>
document.addEventListener("DOMContentLoaded",
function () {
ExecuteOrDelayUntilScriptLoaded(function () {
var ReRenderListView_old = ReRenderListView
ReRenderListView = function (b, l, e) {
ReRenderListView_old(b, l, e)
changeText()
}
}, "inplview.js")
changeText()
}
);
function changeText() {
var element = document.querySelector('#idHomePageNewItem span:nth-child(2)')
element ? (element.innerHTML = "Add item") : null
}
</script>
jQuery version: (This code can replace any number of “new item” text)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
$(document).ready(function () {
var spans = document.getElementsByTagName("span");
for (var i = 0; i < spans.length; i++) {
if (spans[i].innerHTML == "new item") {
spans[i].innerHTML = "add item";
break;
}
}
});
</script>
Source: sharepoint.stackexchange.com
May 17, 2017 / Kannan / 0 Comments
The following code snippet show how to remove duplicate list items in the JSON result of a SharePoint REST call using JavaScript.
Function Definition:
function RemoveDuplicateItems(items, propertyName) {
var result = [];
if (items.length > 0) {
$.each(items, function (index, item) {
if ($.inArray(item[propertyName], result) == -1) {
result.push(item);
}
});
}
return result;
}
Function Usage:
In the below code, assumption is that, the REST call returns data.d.results and the column for which duplicate items need to be removed is Title
var items = data.d.results;
items = RemoveDuplicateItems(items, 'Title');
May 17, 2017 / Kannan / 0 Comments
Following is a code snippet which show how to pass multiple parameters in JavaScript’s SetTimeout() function.
setTimeout(function () {
CustomFunction(param1, param2, param3, param4, param5);
}, 1000);
May 16, 2017 / Kannan / 0 Comments
The following code shows how to refresh web part without refreshing page in SharePoint.
// Set Ajax refresh context
var eventAjax = {
currentCtx: ctx,
csrAjaxRefresh: true
};
// Initiate Ajax Refresh on the list
AJAXRefreshView(eventAjax, SP.UI.DialogResult.OK);
Source: https://pradiprathod.wordpress.com/2015/05/04/how-to-refresh-list-view-in-sharepoint-2013-using-javascript/
May 11, 2017 / Kannan / 0 Comments
Following is the code which can be used to load JavaScript in sequence.
This code for example loads the reputation.js from SharePoint’s layouts folder & jQuery from site assets.
(function () {
ExecuteOrDelayUntilScriptLoaded(function () {
//sp.runtime.js has been loaded
ExecuteOrDelayUntilScriptLoaded(function () {
//sp.js has been loaded
SP.SOD.registerSod('reputation.js', SP.Utilities.Utility.getLayoutsPageUrl('reputation.js'));
SP.SOD.registerSod('jquery-3.2.1', '../SiteAssets/Scripts/jquery-3.2.1.min.js');
SP.SOD.loadMultiple(['reputation.js', 'jquery-3.2.1'], function () {
//reputation.js & jquery-3.2.1.min.js have been loaded.
var context = SP.ClientContext.get_current();
var web = context.get_web();
//Check if jQuery has been loaded
if (typeof jQuery != 'undefined') {
console.log("Jquery is loaded");
}
else {
console.log("Jquery is not loaded!");
}
});
}, "sp.js");
}, "sp.runtime.js");
})();
Source: https://sharepoint.stackexchange.com/questions/92082/uncaught-typeerror-cannot-read-property-get-current-of-undefined
May 5, 2017 / Kannan / 0 Comments
Recently I was trying to setup a development machine at our office and realized few issues.
- The machine didn’t have administrative privileges
- It was located behind the corporate proxy
- It uses Windows 10 as primary OS
So how to proceed? Following is what I did.
[Update: Now node.js includes npm, so I would suggest to download only node.]
Downloading Node.js & NPM
- Download the Node.js binary instead of installer from the below URLs
Node.js binary (32bit or 64 bit): https://nodejs.org/en/download/
Download NPM binary release from the url below
NPM Release: https://github.com/npm/npm/releases
- Extract Node.js to D:\Development\Node
Extract NPM to D:\Development\NPM
Set up environment
Every time the development environment is booted do the following
- Start a command prompt and set the following path
set PATH=%PATH%;D:\Development\Node;D:\Development\Node\node_modules\npm\bin;
- Check the Node version by typing the following
node -v
- Check the NPM version by typing the following
npm -v
If you get version numbers for both then both are working.
- Now set proxy so that NPM can download modules by running the following
set http_proxy=http://replace-with-your-organization-proxy-url:optional-port-number
set https_proxy=https://replace-with-your-organization-proxy-url:optional-port-number
npm config set strict-ssl false
npm config set proxy http://replace-with-your-organization-proxy-url:optional-port-number
npm config set https-proxy https://replace-with-your-organization-proxy-url:optional-port-number
Now the environment is set up.
Do remember, once the console is closed, all the above settings are lost and needs to be run again, just follow the section “Set up environment” again or do the following.
You can set up the “path” variable without administrator privileges in Windows by doing the following.
- From Windows’s Start Menu, open Control Panel.
- In Control Panel open “User Accounts”.
- In ‘User Accounts” open “Change my environment variables”.
- This will open the user’s “Environment Variables” window.
- Select the row with entry “Path”.
- Click “Edit” button.
- In the “Variable value:” text box, append the path of your executable location, which in this case is “D:\Development\Node;D:\Development\Node\node_modules\npm\bin;“
- Click OK
- Open a new terminal or console
- Type “node -v” to check if node is working fine.
- type “npm -v” to check if npm is working fine.
Source URLs:
http://abdelraoof.com/blog/2014/11/11/install-nodejs-without-admin-rights
http://www.kscodes.com/misc/how-to-set-path-in-windows-without-admin-rights/
January 11, 2017 / Kannan / 0 Comments
This post talks about a code which can copy new appointnments and meetings from one Microsoft Outlook calendar to another Microsoft Outlook calendar.
The code is capable of adding new, updating existing and deleting existing items.
One of the issues I was facing while working with my clients was, they had their own email system and they used to send appointment/meeting requests in those accounts for which I had a separate mail ID. For me it was becoming difficult to track all of them. So I was thinking about a way where all the calendar appointments/meetings across multiple clients get added to my own calendar.
While researching on this, came across a superb post Copy New Appointments to Another Calendar using VBA – Slipstick Systems and made use of it.
The code in the post works as is except for 2 things which I have listed below.
- The post uses default calendar as source and I wanted multiple calendar. For this instead of using “GetDefaultFolder” I used “GetFolderPath”. Do note that each instance of calendar required specific functions to be repeated. (I am planning to optimise this code so that the functions remain same but we can use multiple folders.)
- The post’s delete functionality was not working due to an issue where the delete function was comparing the GUID with starting character as “[“, which I had to comment out.
Following is the final code which worked for me.
Full credit goes to Diane Poremsky
'Macro to copy calendar items from current default calendar to another calendar
'Source: https://www.slipstick.com/developer/copy-new-appointments-to-another-calendar-using-vba/
Dim WithEvents curCal As Items
Dim WithEvents DeletedItems As Items
Dim newCalFolder As Outlook.folder
Private Sub Application_Startup()
Dim NS As Outlook.NameSpace
Set NS = Application.GetNamespace("MAPI")
' calendar to watch for new items
Set curCal = NS.GetDefaultFolder(olFolderCalendar).Items 'If you need to use a specific folder then use "NS.GetFolderPath("data-file-name\calendar").Items" and generally "data-file-name" is "user@domain.com"
' watch deleted folder
Set DeletedItems = NS.GetDefaultFolder(olFolderDeletedItems).Items 'If you need to use a specific folder then use "NS.GetFolderPath("data-file-name\Deleted Items").Items" and generally "data-file-name" is "user@domain.com"
' calendar moving copy to
Set newCalFolder = GetFolderPath("data-file-name\calendar")
Set NS = Nothing
End Sub
Private Sub curCal_ItemAdd(ByVal Item As Object)
Dim cAppt As AppointmentItem
Dim moveCal As AppointmentItem
' On Error Resume Next
'remove to make a copy of all items
If Item.BusyStatus = olBusy Then
Item.Body = Item.Body & "[" & GetGUID & "]"
Item.Save
Set cAppt = Application.CreateItem(olAppointmentItem)
With cAppt
.Subject = "Copied: " & Item.Subject
.Start = Item.Start
.Duration = Item.Duration
.Location = Item.Location
.Body = Item.Body
End With
' set the category after it's moved to force EAS to sync changes
Set moveCal = cAppt.Move(newCalFolder)
moveCal.Categories = "moved"
moveCal.Save
End If
End Sub
Private Sub curCal_ItemChange(ByVal Item As Object)
Dim cAppt As AppointmentItem
Dim objAppointment As AppointmentItem
On Error Resume Next
' use 2 + the length of the GUID
strBody = Right(Item.Body, 38)
For Each objAppointment In newCalFolder.Items
If InStr(1, objAppointment.Body, strBody) Then
Set cAppt = objAppointment
End If
Next
With cAppt
.Subject = "Copied: " & Item.Subject
.Start = Item.Start
.Duration = Item.Duration
.Location = Item.Location
.Body = Item.Body
.Save
End With
End Sub
Private Sub DeletedItems_ItemAdd(ByVal Item As Object)
' only apply to appointments
If Item.MessageClass <> "IPM.Appointment" Then Exit Sub
' if using a category on copied items, this may speed it up.
If Item.Categories = "moved" Then Exit Sub
Dim cAppt As AppointmentItem
Dim objAppointment As AppointmentItem
Dim strBody As String
On Error Resume Next
' use 2 + the length of the GUID
strBody = Right(Item.Body, 38)
'If Left(strBody, 1) <> "[" Then Exit Sub 'This particular line didn't work for me
For Each objAppointment In newCalFolder.Items
If InStr(1, objAppointment.Body, strBody) Then
Set cAppt = objAppointment
cAppt.Delete
End If
Next
End Sub
Public Function GetGUID() As String
GetGUID = Mid$(CreateObject("Scriptlet.TypeLib").GUID, 2, 36)
End Function
Function GetFolderPath(ByVal FolderPath As String) As Outlook.folder
Dim oFolder As Outlook.folder
Dim FoldersArray As Variant
Dim i As Integer
On Error GoTo GetFolderPath_Error
If Left(FolderPath, 2) = "\\" Then
FolderPath = Right(FolderPath, Len(FolderPath) - 2)
End If
'Convert folderpath to array
FoldersArray = Split(FolderPath, "\")
Set oFolder = Application.Session.Folders.Item(FoldersArray(0))
If Not oFolder Is Nothing Then
For i = 1 To UBound(FoldersArray, 1)
Dim SubFolders As Outlook.Folders
Set SubFolders = oFolder.Folders
Set oFolder = SubFolders.Item(FoldersArray(i))
If oFolder Is Nothing Then
Set GetFolderPath = Nothing
End If
Next
End If
'Return the oFolder
Set GetFolderPath = oFolder
Exit Function
GetFolderPath_Error:
Set GetFolderPath = Nothing
Exit Function
End Function