ವರ್ಗ ಆರ್ಕೈವ್ಸ್: Angular

Trouble-shooting Tip For Angular Directives (ಅಥವಾ, Learning To Love Hyphens All Over Again)

I have a couple of apps that make $http.get() calls and I wanted to be able to show a nicely formatted error message with ugly error details hidden, but accessible.  ಮೂಲತಃ, ಈ:

image

And then if the user clicks on the error, they see more info:

image

Simple stuff.  Since the exact same potential error can appear in the administrative screen as well as the end user screen, it clearly called for a custom Angular directive.  ನಾನು  found this outstanding series of articles (http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-i-the-fundamentals) by the great Dan Wahlin.  Following his advice, I very quickly created a <hello-world> directive and moved on to my more complex error display squeegee. I ran into a bit of trouble with this more complex directive.  Happily, sort of by chance, I had told WebStorm (the editor I use these days) that the JS file was an Angular file and it helped me figure out the issue.  This is the code for the directive itself:

angular.module("CDLApp").directive("generalCdlErrorHandler", ಕ್ರಿಯೆ() {

ಮರಳಿ {
restrict: "E",
ಬದಲಿಗೆ: ನಿಜವಾದ,

scope: {
retrieveLastConfigurationError: "&"
},

ಪ್ರಮಾಣ ಫಲಕ:
'<div class="alert alert-danger" role="alert" ng-init="doShowExpandedErrorDetails = true" ng-show="retrieveLastConfigurationError()">' +
' There was an I/O error or other error. This usually happens because configuration data file could not be ' +
' found or the configuration file contains inaccurate information (such as referencing a document library ' +
' that does not exist).' +
' <br />' +
' <div ng-show="doShowExpandedErrorDetails">' +
' <a href="#" ng-click="doShowExpandedErrorDetails = ! doShowExpandedErrorDetails">' +
' Click here to hide details.' +
' </ಒಂದು>: ' +
' <br />' +
' <pre>{{retrieveLastConfigurationError() | json}}</pre>' +
' <br />' +
' </div>' +
' <div ng-show="!doShowExpandedErrorDetails">' +
' <a href="#" ng-click="doShowExpandedErrorDetails = ! doShowExpandedErrorDetails">' +
' Click here to expand error details.' +
' </ಒಂದು>' +
' </div>' +
'</div>'
};
});

ಮೂಲತಃ, I’m creating a new element called a “generalCdlErrorHandler”.  It needs access to a function called retrieveLastConfigurationError and that’s handled in the scope object.  I probably could have just used the parent’s scope, but that feels lazy.  If anyone thinks I should have done that, I’d love to hear about it in the comments.

This was all fine, but I wasn’t getting anything.  No errors popped up in the console (at least once I fixed all the sx errors I created along the way).  I simply didn’t get any output from the directive.  I went and added some static text before the ng-show directive and I *did* get that. This made me think that perhaps the directive wasn’t allowed to implicitly create new vars like “doShowExpandedErrorDetails” or have an “ng-init” in there. 

I went back into the HTML to see if I had a type and this time WebStorm helped me out.  I had been passing in the retrieveLastConfigurationError function like this:

<general-cdl-error-handler retrieveLastConfigurationError="CDLController.retrieveLastConfigurationError()">
</general-cdl-error-handler>

But it really needed to be this:

<general-cdl-error-handler retrieve-last-configuration-error="CDLController.retrieveLastConfigurationError()">
</general-cdl-error-handler>

WebStorm was smart enough to know that it had to be hyphenated.  If it hadn’t provided that hint, I’d probably be still troubleshooting this ಸ್ಮೈಲ್.  Fun times!

The trick is this: not only is the directive element name hyphenated, so are any attributes you add to it.  Once I added the hyphens, it all worked great.  Dan’s tutorial happened to use short single names, so I didn’t make the connection.

ಈ ಯಾರಾದರೂ ಸಹಾಯ ಭಾವಿಸುತ್ತೇವೆ.

</ಕೊನೆಯಲ್ಲಿ>

undefinedನನ್ನ ಬ್ಲಾಗ್ ಚಂದಾದಾರರಾಗಿ.

ನಲ್ಲಿ ಟ್ವಿಟ್ಟರ್ ನನ್ನನ್ನು ಅನುಸರಿಸಿ http://www.twitter.com/pagalvin

HTTP 406 ದೋಷ ಶೇರ್ಪಾಯಿಂಟ್ ಉಳಿದ ಅಂಶಗಳು ಅಭಿಪ್ರಾಯ ವಿರುದ್ಧ ಕೋನೀಯ $ http.get ಬಳಸುವಾಗ

ನವೀಕರಿಸಿ: Marc AD ndersson pointed out this great piece of info: HTTP://blogs.office.com/2014/08/13/json-light-support-rest-sharepoint-api-released/. That explains a lot :).

That may be the worst title of a blog post ever! Anyhoo.

I typically do all of my prototyping against an O365 instance. I have my personal instance so that I don’t have to be worried about affecting anyone else. As an aside – remember when we call carried around virtual machines on our laptops with MOSS – SQL Server, IIS, deciding Hyper-V vs. VMWare? Anyhoo…

I had developed an app using Angular in this environment that does, ಇತರ ವಿಷಯಗಳ ನಡುವೆ, ಈ:

$http.get(serverUrl)
.success(ಕ್ರಿಯೆ(ದಶಮಾಂಶ, ಅಂತಸ್ತು, headers, ಸಂರಚನಾ) {

var getLinksResponse = data;

getLinksResponse.value.forEach(ಕ್ರಿಯೆ(theResult) {

// and so on and so froth

This was working just fine in two different SharePoint online environments. ಹೇಗಾದರೂ, when my colleague ported it to a Cloudshare instance, he was getting an HTTP 406 ದೋಷ (which was the first time I ever got that one, so … yay, I guess). We did a bit of research and noticed that the “Accept” header was off. SharePoint online was perfectly happy with:

Accept: application/json

But the cloudshare instance (which is SP on prem, hosted in a virtual server) wanted the classic “odata=verbose” added in as well:

Accept: application/json;odata=verbose

To fix that, we added the header as such:

var config = {headers: {
‘Accept’: ‘application/json;odata=verbose’
}
};

$http.get(serverUrl,ಸಂರಚನಾ)
.success(ಕ್ರಿಯೆ(ದಶಮಾಂಶ, ಅಂತಸ್ತು, headers, ಸಂರಚನಾ) {

var getLinksResponse = data;

getLinksResponse.value.forEach(ಕ್ರಿಯೆ(theResult) {

// and so on and so froth

That got rid of the 406, but it also changed the format of the response. It was more … verbose. (haha!) More changes were required and here’s the final result:

var config = {headers: {
‘Accept’: ‘application/json;odata=verbose’
}
};

$http.get(serverUrl,ಸಂರಚನಾ)
.success(ಕ್ರಿಯೆ(ದಶಮಾಂಶ, ಅಂತಸ್ತು, headers, ಸಂರಚನಾ) {

var getLinksResponse = data;

getLinksResponse.d.results.forEach(ಕ್ರಿಯೆ(theResult) {

// and so on and so froth

This only turned into a 30 minute problem for us, so we lucked out. Hopefully someone finds this useful.

</ಕೊನೆಯಲ್ಲಿ>

ಹೇಗೆ: ಅದೇ ಪುಟದಲ್ಲಿ ಬಹು ಕೋನೀಯ ಶೇರ್ಪಾಯಿಂಟ್ ವೆಬ್ ಪಾರ್ಟ್ಸ್ ಸಕ್ರಿಯಗೊಳಿಸಿ

This blog posts describes how you can have multiple Angular.js based SharePoint web parts (referenced via a content editor web part) on the same page. I’m calling a content editor web part (CEWP) that references JavaScript built using the Angular.js framework an “Angular Web Part.”

Angular’s bootstrap process is super easy and just about every example you find on the internets goes something like this:

<html ng-app=’myApp’>

<blah/><blah/><blah/>

</HTML>

This breaks down, ಹೇಗಾದರೂ, if you want to enable multiple CEWP’s representing multiple angular web parts on the same page. Angular will only automatically bootstrap against the first ng-app directive it finds – at least as of angular version 1.3.6. The solution is pretty simple – manually bootstrap your code instead. The above now changes to something like this:

<ದೇಹ>
<ಡಿ
iv id=”bootstrapHere” ng-controller=”myController as theController”>
<blah/><blah/><blah/>
</div>
</ದೇಹ>

<script src=”//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.js”></ಸ್ಕ್ರಿಪ್ಟ್>

<ಸ್ಕ್ರಿಪ್ಟ್>
angular.bootstrap(angular.element(document.getElementById(“bootstrapHere”)),[‘myApp’]);
</ಸ್ಕ್ರಿಪ್ಟ್>

ಮೂಲತಃ, instead of using ng-app on the element to do your bootstrapping, you slap an ID onto that element. ನಂತರ, use the bootstrap() method on angular itself to control the bootstrapping process at run-time. I’ve tested this with three different Angular web parts on the same page and it works a charm.

</ಕೊನೆಯಲ್ಲಿ>

undefinedನನ್ನ ಬ್ಲಾಗ್ ಚಂದಾದಾರರಾಗಿ.

ನಲ್ಲಿ ಟ್ವಿಟ್ಟರ್ ನನ್ನನ್ನು ಅನುಸರಿಸಿ http://www.twitter.com/pagalvin