Error: [$parse:syntax] while passing a method definition as String - angularjs

I'm working on a project using AngularJS. What I'm trying to do is to write my method's definition on my controller and pass it as string to be execute on a click even in client side:
And here is an example of what I'm trying to do:
My controller:
$scope.myMethod = "add({'a':3,'b':4})";
add (o)
{
return o.a+o.b;
}
My HTML page:
<button ng-click={{ myMethod }} ></button>
But I keep getting the Error: [$parse:syntax].
Can you tell me what I'm doing wrong?

The binding will insert the whole string:
"content"
That is to say, it inserts " inline, and since attribute values are enclosed by " as well, the inserted " ends the value expression prematurely. The rendered HTML looks like this:
ng-click=""add({'a':3,'b':4})""
Guard the binding with ', like this:
ng-click="'{{myMethod}}'"
I don't agree with the way you're inserting a method into the HTML, nor am I sure it works, but the above will fix the $parse error.

Related

How do I test controller as syntax with protractor?

I'm currently writing some Protractor tests for an app. But in the app i'm using controller as syntax as the pieces I want to work on are components. The problem is that when i use the selector of "" $ctrl.functionName"" it's giving me an illegal selector statement.
Anyone have any ideas about this?
let btn = $$("button[ng-click^=$ctrl.initRequest].secondary.bf-btn");
expect(btn.isDisplayed()).toBe(true);
The error message is
Failed: invalid selector: An invalid or illegal selector was specified
If you cannot assign a meaningful id or other attribute to the element, you need to fix your current selector. At the very least, there should be quotes around the ng-click value:
button[ng-click^='$ctrl.initRequest'].secondary.bf-btn
Note that a slightly better version, that would also not require quotes, would be to use a partial match:
button[ng-click*=initRequest].secondary.bf-btn
And, see if you can drop the questionable classes and have just:
button[ng-click*=initRequest]

Angular Infdig Error, but function is running properly

I am continuously getting 'Error: $rootScope:infdig
Infinite $digest Loop' on my app, but the actual function that is causing it is still displaying properly in the browser.
Inside my controller, I am creating the following function:
$scope.time = function(id){
return new Date(parseInt(id.substring(0, 8), 16) * 1000);
}
In my HTML, I am trying to show the time that a blog post was created by pulling in the post's mongoDB id, which I convert to the appropriate format in the $scope.time function:
<span am-time-ago="time(post._id)"></span>
From console.logs and testing in the controller, I can see that:
The correct id is being pulled in from Mongo
The $scope.time() function is correctly converting the id into a date string
The date string is showing up the way I want in the browser
So, what is causing the infinite loop and how can I remove it while still showing the data in this same format?
Any help/ideas would be greatly appreciated!
I'm basing this answer on the assumption that you are using angular-moment.
It looks like angular-moment 'am-time-ago' directive is expecting a model value so it will keep invoking your time function resulting in infinite digest cycles.
So rather construct the time when you get your model and pass this value to the 'am-time-ago' directive. Something like this:
$scope.post.$time = $scope.time($scope.post._id);
and your markup would be
<span am-time-ago="post.$time"></span>
See plunker. Open the console to view when the error occurs.

how to find element in protractor test?

Trying to check the value of this element on an angular plunker:
it('should display valid',function(){
browser.get('http://embed.plnkr.co/3nt01z/preview');
var errortext =element(By.xpath('body>div>h2>span:nth-child2)')).getText);
expect(errortext).toBe('Not:(');
})
Getting an error though:
Stacktrace:
InvalidSelectorError: invalid selector: Unable to locate an element with the xpath expression body>div>h2>span:nth-child(2) because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string 'body>div>h2>span:nth-child(2)' is not a valid XPath expression.
Is there a better way to find this span element or what is the right xpath expression?
I think you meant By.cssSelector(...).
By.xpath expects an XPath expression, which would be something like /body/div/h2/span[2], although I'm not sure about the exact syntax.
By the way, your code would be easier to test if you added an ID or CSS class to the element, so you don't need to depend on the exact DOM structure.
Try to use element(by.css('some css selector'))
Also, you have a typo in code - getText; instead of getText();
Or try this:
var errortext = element(By.xpath('/body/div/h2/span[2]')).getText();

Adding files to $scope in AngularJS controller

I have the following input element:
 <div class="form-group">
    <label>Attach BOL Document</label>
       <input name="file" type="file" class="form-control" onchange="angular.element(this).scope().uploadFile(this.files)" />
 </div>
In my controller (outside of any function) I set a variable like this:
$scope.fd = new FormData();
and I have the following function defined that fires onchange of the input element as seen above:
$scope.uploadFile = function (files) {
console.log(files[0]);
$scope.fd.append("file", files[0]);
console.log($scope.fd);
};
The first console.log outputs the File object as I expect so I know that is being passed into my $scope. The problem is the second console.log outputs an empty FormData object. The File object is not getting appended??
I thought maybe this was something to do with the fact that I am declaring $scope.fd outside of the UploadFIle function, but even declaring it inside the function does not work...
Why???
Well I figured out whats going on here. Its got nothing to do with AngularJs. You cannot inspect the keys added to a FormData object. See this question for a reference
How to inspect FormData?
This really stinks... So until I get the server side code ready and I actually POST the data I cant tell if the file is actually getting appended. I feel certain it is however I cant validate this.

Error appending Pagedown in AngularJS Directive

Based on this question, though I felt this warranted its own question: Google pagedown AngularJS directive
Following the example from this question, it seems to work, however I am running into issues when I try to append a directive to the page.
Here is the code I have in the linking function:
scope.editor_id = null;
if(attrs.id == null) {
scope.editor_id = nextID++;
} else {
scope.editor_id = attrs.id;
}
//append editor HTML
//has to be done here so that it is available to the editor when it is run below
var editor_html = $compile(
'<div id="wmd-button-bar-' + scope.editor_id + '"></div>' +
'<textarea class="wmd-input" id="wmd-input-' + scope.editor_id + '" ng-model="content"></textarea>'
)(scope);
element.find('.wmd-panel').append(editor_html);
var editor = new Markdown.Editor(editor_converter, "-" + scope.editor_id);
editor.run();
However, when I append one of these to the document, I get the following error:
TypeError: Cannot read property 'attachEvent' of null
This error tends to crop up when the wmd-input is not present in the HTML. however, I am adding it with the $compile function, and it works on page load, but not when it is appended. What am I doing wrong here?
UPDATE
I was able to reproduce your problem: http://plnkr.co/edit/R2eDKBreHmYBjPtU0JxD?p=preview
Why typeError: Cannot read property 'attachEvent' of null?
I was wrong with my previous assumption ( the composite linking function do returns the element)
The problem is with the way you use angular.element#find.
angular.element#find only search for child elements not on the whole document.
the DOM element with a .wmd-panel class is not a child of the current element.
This should work fine:
angular.element('.wmd-panel').append(editor_html);
Try doing compile like this:
$compile('template stuff goes here')(scope, function(cloned, scope){
element.append(cloned);
});
You may also have to define your editor inside the callback function because I'm not sure if it's asynchronous or not. You may also want to re-consider having your directive compile and append to itself like this. Why not just add more instances of the entire directive using something like ng-repeat?
Also, if you have multiple instances inside this one directive, you will lose reference to editor. Not sure what's going on outside this code so I can't really tell.

Resources