Tips and Hints on Angular 2 Modules Usage

What is Angular 2 module?

"Simply it's like a box which encapsulates angular components"

import { NgModule } from '@angular/core';

@NgModule({})
  • Class which decorated with NgModule
  • Arrange code in modular way
  • Extend our application with external modules

Some useful tips as below; 

Tip #1

Every application must bootstrap one component, which known as “root application component”.

bootstrap: [
AppComponent
]

Tip #2

Every components, directives and pipes must only belong to only one Angular module.

Because we follow singleton design pattern.

Tip #3

Only declare components, directives and pipes under declarations array.

declarations: [
AppComponent
, AppFilterPipe
, AppDirective
]

Tip #4

Never re-declare modules belongs to another module, because if we do so we polluting core objective of Angular modules.

Tip #5

All declared components are private by default and only accessible to current module unless explicitly export them.

Tip #6

To consume directives within template, you must declare directive within the module or imported from external module.

Tip #7

Export/ Re-export components, directives & pipes when ever who need, means that you are not restrict on that.

Tip #8

No need of any imports to export our components, directives and pipes.

Tip #9

Never export services and declare those within providers array, since then its shared within all module.

providers: [AppGuard]

Tip #10

Imported components, directives, pipes (it can be Angualar or 3rd party) makes available any exported module consumable within our module.

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

@NgModule({
//external component imports,
imports: [
BrowserModule
, FormsModule
}
})

Tip #11

Importing module does not mean that you have access to its imported modules. Simply imports are not inherited!

Tip #12

Avoid declaring services of shared modules in providers array since we must ensure modules not imported my times in the app.

Tip #13

Route guards must be declared within providers since navigation control is applicable to app level.

Advertisements

Why file extension is not mentioned when importing exporting modules in Angular 2 App

Angular 2 modules are handled by SystemJS (https://www.npmjs.com/package/systemjs) module loader. Since we mention module extensions to be loaded in the “systemjs.config” which describes as below, so that no need of defining extension.

Notes: app is the root folder or the main app component of this angular application and your default extensions to be loaded would be JavaScripts.

[Improved Post] Update SharePoint Metadata (Taxonomy) column with Angular JS

After earlier post on the same topic which is updating taxonomy (managed metadata) column with Angular and with JSOM. Thought of optimize the code with more readable and with JavaScript promises. There may be areas further to be improved, for now sample code as below;

(function () {
 'use strict';

 // define controller
 var controllerId = "MMSDevCtrl";

 angular
 .module('app')
 .controller(controllerId, ['$q', mmsDevController]);

 // create controller
 function mmsDevController($q) {

 //global var
 var vm = this;

 //value definitions
 var siteUrl = 'http://win2012/sites/MSSDevTest';
 var listName = 'MyDocumentLibrary';
 var fieldName = 'MMSDepartments'; //MMS Column one
 var fieldName2 = 'MMSDevLanguages'; //MMS Column two
 var itemIdUpdating = 1; // Item to be udated
 var termLabel = 'IT'; //'';
 var termLabel2 = 'Java'; //'';
 //add metadata column to sharepoint
 vm.submitMetadata = function () {
 // function for update managed metadata column
 SetManagedMetaDataField();
 }

 // Setting managed metadata to SharePoint List or Library
 function SetManagedMetaDataField() {
 var context = new SP.ClientContext(siteUrl);
 //Get item form ID
 var list = context.get_web().get_lists().getByTitle(listName); //listName
 var item = list.getItemById(itemIdUpdating); //itemID
 //MMS columns
 var field = list.get_fields().getByInternalNameOrTitle(fieldName); //Tx field one
 var txField = context.castTo(field, SP.Taxonomy.TaxonomyField);
 var field2 = list.get_fields().getByInternalNameOrTitle(fieldName2); //Tx fieldName two
 var txField2 = context.castTo(field2, SP.Taxonomy.TaxonomyField);

 //loading context
 context.load(field);
 context.load(txField);
 context.load(field2);
 context.load(txField2);
 context.load(item);

 //excute async of context
 context.executeQueryAsync(
 //Success
 Function.createDelegate(this
 , function () {
 //Getting term set IDs of the fields
 var termSetId = txField.get_termSetId().toString();
 var termSetId2 = txField2.get_termSetId().toString();

 //Getting ID for term
 getTermIdForTerm(context, termLabel, termSetId)
 .then(function (termID) {
 console.log("Returned term Id", termID);
 //check for not multi valued taxonomy column
 if (!txField.get_allowMultipleValues()) {
 var termValue = new SP.Taxonomy.TaxonomyFieldValue();
 termValue.set_label(termLabel);
 termValue.set_termGuid(termID);
 termValue.set_wssId(-1);
 txField.setFieldValueByValue(item, termValue);
 }
 });

 getTermIdForTerm(context, termLabel2, termSetId2)
 .then(function (termID) {
 console.log("Returned term Id 2", termID);
 //check for not multi valued taxonomy column
 if (!txField2.get_allowMultipleValues()) {
 var termValue2 = new SP.Taxonomy.TaxonomyFieldValue();
 termValue2.set_label(termLabel2);
 termValue2.set_termGuid(termID);
 termValue2.set_wssId(-1);
 txField2.setFieldValueByValue(item, termValue2);
 }
 });

 // Define other columns to be updated
 item.set_item('Title', 'New Item 9102016 C');
 // Update item
 item.update();
 //Execute query for update
 context.executeQueryAsync(
 function () {
 console.log('field updated with MMS column #TechCentro');
 }, function (sender, args) {
 console.error(args.get_message() + '\n' + args.get_stackTrace());
 });
 }
 , function (sender, args) {
 console.log(args.get_message() + '\n' + args.get_stackTrace());
 })
 //Failed
 , Function.createDelegate(this, function (err) {
 console.error(err.get_message());
 })
 )
 }
 // Getting ID of the Term
 function getTermIdForTerm(clientContext, termValue, termSetId) {
 var deferred = $q.defer();
 var termId = "";
 var tSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
 var ts = tSession.getDefaultSiteCollectionTermStore();
 var tset = ts.getTermSet(termSetId);
 var lmi = new SP.Taxonomy.LabelMatchInformation(clientContext);
 lmi.set_lcid(1033);
 lmi.set_trimUnavailable(true);
 lmi.set_termLabel(termValue);
 var termMatches = tset.getTerms(lmi);
 //context loading with taxanomy values
 clientContext.load(tSession);
 clientContext.load(ts);
 clientContext.load(tset);
 clientContext.load(termMatches);
 clientContext.executeQueryAsync(
 function () {
 if (termMatches && termMatches.get_count() > 0) {
 termId = termMatches.get_item(0).get_id().toString();
 deferred.resolve(termId);
 console.log("Resolved Term Id for Term " + termValue, termId);
 }
 else
 deferred.resolve(null);
 }, function (sender, args) {
 console.log("Error on retrieving term GUID", args);
 deferred.reject(null);
 });
 return deferred.promise;
 }

 };

})();

Markup as below;


<script src="../../_layouts/15/SP.Runtime.js"></script>
<script src="../../_layouts/15/SP.js"></script>
<script src="../../_layouts/15/SP.Taxonomy.js"></script>
<script src="../Scripts/angular.js"></script>
<script src="../Scripts/App.js"></script>
<script src="../Scripts/mmsDev.controller.js"></script>
<div ng-app="app" ng-controller="MMSDevCtrl as vm">
{{}}
<input id="Text1" type="text" ng-model="vm.value"/>
<input id="Submit1" type="button" value="submit" ng-click="vm.submitMetadata()"/></div>

Click here to view old post.

Get | Resolve Term ID for Term Value in SharePoint Metadata Service

This may be generic function you can use when you play with managed metadata (taxonomy) columns or with Managed Managed Metadata Service.

Notes:

  • Used JSOM since no impletation in REST API to get done this task in SharePoint to date of post
  • Passing term set ID is must since there may may be many term values equivalent in the term store
  • For the example, I have retrieved the term set ID from the list field which glued with the managed metadata service.

Following code illustrate how to get term ID for term value provided.


// Resolve Term ID for the Term Value 
 function getTermIdForTermValue(siteUri, listName, fieldName, termValue) {
 //Define
 var deferred = $q.defer()
 , termId;
 var clientContext = new SP.ClientContext(siteUrl);
 var list = clientContext.get_web().get_lists().getByTitle(listName);
 //Tx field
 var field = list.get_fields().getByInternalNameOrTitle(fieldName);
 var txField = clientContext.castTo(field, SP.Taxonomy.TaxonomyField);
 //load context
 clientContext.load(field);
 clientContext.load(txField);
 // //excute async of context
 clientContext.executeQueryAsync(
 //Success on Async
 Function.createDelegate(this
 , function () {
 //Getting term set of the field
 var termSetId = txField.get_termSetId().toString();
 var tSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
 var ts = tSession.getDefaultSiteCollectionTermStore();
 var tset = ts.getTermSet(termSetId);
 //Define term label to match
 var lmi = new SP.Taxonomy.LabelMatchInformation(clientContext);
 lmi.set_lcid(1033);
 lmi.set_trimUnavailable(true);
 lmi.set_termLabel(termValue);
 var termMatches = tset.getTerms(lmi);
 //context loading with taxanomy values
 clientContext.load(tSession);
 clientContext.load(ts);
 clientContext.load(tset);
 clientContext.load(termMatches);
 clientContext.executeQueryAsync(
 function () {
 if (termMatches &amp;&amp; termMatches.get_count() &gt; 0) {
 termId = termMatches.get_item(0).get_id().toString();
 console.log("Resolved Term Id for Term " + termValue, termId);
 deferred.resolve(termId);
 }
 else {
 console.log("No IDs to resolved for Term " + termValue);
 deferred.resolve(null);
 }
 }
 , function (sender, args) {
 console.log("Error on resolving term ID", args);
 deferred.reject(null);
 });
 }
 , function (sender, args) {
 console.log(args.get_message() + '\n' + args.get_stackTrace());
 })
 //Failed on Async
 , Function.createDelegate(this, function (err) {
 console.error(err.get_message());
 })
 );
 return deferred.promise;
 }

Click here to view in gist.

For more details refer following links;

Update SharePoint Metadata (Taxonomy) column with Angular JS

Check following code which updates provided SharePoint list/ library item with Managed metadata column.

First it solves GUID from the Managed Metadata service then push that value and other column values to the SharePoint back end.

Before execute following code you need properly configured “Managed Metadata Service” and list configuration with MMS.

Click here above is not visible.

If this code helped, don’t miss to give feedback and following!

Managed Metadata Column Value Add with Angular | JavaScript & JSOM | CSOM

Following would be high-level program flow;MMS Column Update Program Flow

SP Taxonomy need to be imported.


var scriptbase = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/";
$.getScript(scriptbase + "SP.Taxonomy.js");

Create custom list item with metadata column in SharePoint with JSOM and Angular JS.

// Adding item to SharePoint custom list with Managed Metadata column (MMS column) with JSOM
(function () {
    'use strict'; 

    // define controller
    var controllerId = "mmsColumnUploadCtrl"; 

    angular
        .module('app')
        .controller(controllerId, ['$scope', mmsColumnUploadCtrl]); 

    // create controller
    function mmsColumnUploadCtrl($scope) {
        //global var
        var vm = this;

        //add metadata column to sharepoint
        vm.AddMetadataColumn = function () {
            var scriptbase = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/"; 

            // create list item with MMS column
            $.getScript(scriptbase + "SP.Taxonomy.js", createListItemWithMMSColumn); 

        } 

        //Create list item metadata with MMS column
        function createListItemWithMMSColumn() {
            //site URi
            var siteUrl = 'http://<site url>/sites/MMSPOC';
            // List name of updating
            var listName = 'TestList';// List name
            //Term GUID get from Service
            var termId = 'ed414e70-cc02-444b-ba78-8456e6495e45';//term GUID
            //For multi labled column may need to provice term lable also, else no
            //var termLabel = 'ABCTEST';//Term label

            // Client context
            var clientContext = new SP.ClientContext(siteUrl);
            var oList = clientContext.get_web().get_lists().getByTitle(listName);
            var itemCreateInfo = new SP.ListItemCreationInformation();
            var oListItem = oList.addItem(itemCreateInfo);
            // Define item
            oListItem.set_item('Title', 'New Item!'); // non MMS columns
            oListItem.set_item('MMSCol', termId); //MMS column
            // Update item
            oListItem.update(); 

            //client context..Async Req.
            clientContext.load(oListItem);
            clientContext.executeQueryAsync(
                Function.createDelegate(this, onQuerySucceeded),
                Function.createDelegate(this, onQueryFailed)
             );
        } 

        // On query success
        function onQuerySucceeded(oListItem) {
            console.info('Item created!');
        }
        // On query failed
        function onQueryFailed(sender, args) {
            console.error('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
        } 

    }; 

})();

Update document library items’ managed metadata column in SharePoint with JSOM and Angular

// Adding item to SharePoint "Document Library" with Managed Metadata column (MMS column) with JSOM
(function () {
    'use strict'; 

    // define controller
    var controllerId = "mmsColumnUploadCtrl"; 

    angular
        .module('app')
        .controller(controllerId, ['$scope', mmsColumnUploadCtrl]); 

    // create controller
    function mmsColumnUploadCtrl($scope) {
        //global var
        var vm = this;

        //add metadata column to sharepoint
        vm.AddMetadataColumn = function () {
            var scriptbase = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/"; 

            // Create document item ith MSS column
            $.getScript(scriptbase + "SP.Taxonomy.js", updateDocumentItemWithMMSColumn); 

        } 

        // Create document metadata of document library item with MMS column
        function updateDocumentItemWithMMSColumn() {
            //site URi
            var siteUrl = 'http://<site>/sites/MMSPOC'; 

            // List name of updating
            var listName = 'MMSPOCDocLib';//document library name

            // GUID of the term
            var termId = 'ed414e70-cc02-444b-ba78-8456e6495e45';//term guid

            //For multi-valued terms following will be needed
            var termLabel = 'ABCTEST';//term label

            //Item Id for update in the document library
            //3 is item ID to be updated
			//You may dynamically change with the requirement
            var itemIdUpdating = 3; 

            // Client context
            var clientContext = new SP.ClientContext(siteUrl);
            var oList = clientContext.get_web().get_lists().getByTitle(listName);
            var itemCreateInfo = new SP.ListItemCreationInformation(); 

            var oListItem = oList.getItemById(itemIdUpdating);
            // Define item
            oListItem.set_item('Title', 'Item updated!');
            oListItem.set_item('MMSCol', termId);
            // Update item
            oListItem.update(); 

            //client context..Async Req.
            clientContext.load(oListItem);
            clientContext.executeQueryAsync(
                Function.createDelegate(this, onQuerySucceeded),
                Function.createDelegate(this, onQueryFailed)
             );
        }
        // On query success
        function onQuerySucceeded(oListItem) {
            console.info('Item created!');
        }
        // On query failed
        function onQueryFailed(sender, args) {
            console.error('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
        } 
    };

Await for more interesting coding samples and articles, keep following!! 

Optimize SharePoint REST API with client side caching | Angular JS

If you working with any REST API and having the requirement of getting too many data from the from the DB or lists (in SharePoint) [GET requests]. You may facing slowness in the App, Web Part or in client side web part.

To overcome above issue with the load, one option would be caching of recurring data while you made all other performance improvement points. Following describes how yo improve performance of SharePoint Online/On-prem application which relies on REST API by using caching and uses Angular JS for client side development.

Note: Out of the box (OOTB) Angular JS having caching implementation on the $http, but in following sample I have used “angular-cache” since it give more features such as access to local storage and session storage.

First you should include following references https://github.com/jmdobry/angular-cache/tree/master/dist and include those it in your project.

Secondly, you should configure the caching options. Either you configure caching globally as below on the Angular app.js

//If need to apply all HTTP requests globally

(function () {
'use strict';

// create app
var app = angular.module('app', [
, 'angular-cache'
]);

// startup code
app.run(['$http', 'CacheFactory', function ($http, CacheFactory) {
//cache configs
$http.defaults.cache = CacheFactory('nylFileData', {
maxAge: 15 * 60 * 1000 // Items added to this cache expire after 15 minutes
, cacheFlushInterval: 60 * 60 * 1000 // This cache will clear itself every hour
, deleteOnExpire: 'aggressive' // Items will be deleted from this cache when they expire
, storageMode: 'localStorage' // This cache will use `localStorage`.
});
}]);

Further configurations http://jmdobry.github.io/angular-cache/#configuration-options

Else you can define configurations per Angular service or may be per request.

(function () {
'use strict';
var serviceId = "myService";

angular
.module('app')
.factory(serviceId, ['$http', '$q', 'CacheFactory', myService]);

function myService($http, $q, CacheFactory) {
// init factory
init();

var service = {
getData: getData

};

return service;

//initialization
function init() {
//Cache initialization
CacheFactory('cacheData', {
maxAge: 15 * 60 * 1000 // Items added to this cache expire after 15 minutes
, cacheFlushInterval: 60 * 60 * 1000 // This cache will clear itself every hour
, deleteOnExpire: 'aggressive' // Items will be deleted from this cache when they expire
, storageMode: 'localStorage' // This cache will use `localStorage`
});
}
}
})();

Finally, you should should bind your cache with the request.

 //get data function
function getData() {
var deferred = $q.defer();
var start = new Date().getTime();

//request
$http({
method: 'GET',
cache: CacheFactory.get('cacheData'),
url: webUrl + '/_api/web/lists/getByTitle(\'My List\')/Items',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-Type': 'application/json;odata=verbose'
}
}).then(function successCallback(data) {
// when the response is available
deferred.resolve(data);
console.log('Time to retrieve data - [' + (new Date().getTime() - start) + 'ms]', data, serviceId, false);
}, function errorCallback(error) {
// or server returns response with an error status.
deferred.reject(error);
});

return deferred.promise;
}