Compiling an element with AngularJs attributes after the page is loaded - angularjs

I need to create multiple <a ng-click="controller.doThat(X)"> elemets, based on a response from some $http call. And add them to an element designated by its id attribute.
I am using AngularJs v1.6.4. Please help.

var newElem = $compile(t)($scope);
document.getElementById("designatedDiv").appendChild(newElem[0]);
does the job as long as t is a string of a single element:
var t = "try and press <a ng-click=\"controller.doThat(X)\">here</a> and see..."
will result in:
Error: [jqLite:nosel] http://errors.angularjs.org/1.6.4/jqLite/nosel
at angular.min.js:6
BUT if you redo the last example as following:
var t = "<span>try and press </span><a ng-click=\"controller.doThat(X)\">here</a><span> and see...</span>"
var newElem = $compile(t)($scope);
for (i=0;i<newElem.length;i++)
document.getElementById("designatedDiv").appendChild(newElem[i]);
then it works as expected.

Related

If for some field getText() returns NULL then what other functions could use to get the string of that field?

I was asked this question in an interview.
If you cannot get the string by getText() because it returns NULL. Then how would you get the string of a field in selenium webdriver?
There can be several ways:
Using selenium with getting the attributes of the element:
InnerText can be empty in some cases, thats why you can also try with innerHTML.
var innertext = element.getAttribute("innerText");
var innerHtml = element.getAttribute("innerHTML");
Or you can execute js script
var element = element(by.id('something');
var response = browser.executeScript('var el = arguments[0]; return {text: el.innerText, html: el.innerHTML};', element);
console.log(response.text)
console.log(response.html)
There is also a variant of execute script from selenium, document query element and return the innerText or innerHTML or and other property from it.

Converting table from HTML to Javascript array in AngularJS

This plunk is my attempt to convert an HTML table to a Javascript array using only AngularJS/jqLite. I can get the head and body from the table, however when I try to get the rows from the body object I get the following error (see the console): tbody.children is not a function. How to fix this?
Javascript
var table = angular.element($scope.t);
var thead = table.children()[0];
var tbody = table.children()[1];
console.log(tbody.children());
I've not used this API before, but a quick check reveals that you lose the angular.element benefits when you pick the children(). You can wrap it again like this to access children method again:
var table = angular.element($scope.t)
var thead = angular.element(table.children()[0])
var tbody = angular.element(table.children()[1])
console.log(tbody.children());

how to retrieve data nested in two collections from firebase with angular

I'm new in Angular - Firebase development, and I am having problems to understand how to retrieve data nested in two collections.
I have a collection named "Orders", which includes a field call "auth", which is the user ID, and I have another collection that is the "User Profile", wich it's $id is the value of "auth". Inside the User Profile I have a field named roomNumber, and it's content I that I want to retrieve every time I read, in ng-repeat of the Orders.
In my view I was trying to do something like this :
<tr ng-repeat="item in items | filter: searchKeyword ">
<td align="left">{{item.$id}} - {{roomNumber(item.$id)}}</td></tr>
roomNumber is a function in my controller
$scope.roomNumber = function(id) {
var rootRef = new Firebase("https://xxxx-fire-yyyy.firebaseio.com/userProfile"+ '/' + id);
$scope.userdet = $firebaseArray(rootRef);
rootRef.on("value", function(rootSnapshot) {
var key = rootSnapshot.key();
var childKey = rootSnapshot.child("room").val();
console.log("room ", childKey)
});
return childKey
}
When I run this code and see results in my js console, strange things happend:
1. It repeat a lot of times
2. I can never get the childKey value
I have been reading Firebase documentation, but really I do not understand how to do this "silly" thing, does anybody give me a tip of how to do it?
When you bind a function to the $scope and call it within the html it expects to get an answer back right away when called. So when you query firebase and it takes its sweet time getting you back an answer, angularjs has already gotten an answer of undefined from the function.
So what is happening is that you are registering a callback when you provide the function to rootRef.on and then right after you register the callback you are returning the value of childKey. Unfortunately, childKey only gets set by the callback function (which firebase hasn't executed yet). Therefore angularjs gets an answer of undefined from your roomNumber function.
In order to make this work, you are going to have to get the room numbers beforehand and then probably add them to each of your items in $scope.items then use
<td align="left">{{item.$id}} - {{item.room}}</td></tr>
instead of
<td align="left">{{item.$id}} - {{roomNumber(item.$id)}}</td></tr>
To load all the room numbers you could call some function like this one after $scope.items has loaded
for (var i = 0; i < $scope.items.length; i++) {
var rootRef = new Firebase("https://xxxx-fire-yyyy.firebaseio.com/userProfile"+ '/' + $scope.items[i].$id);
$scope.userdet = $firebaseArray(rootRef);
rootRef.on("value", function(rootSnapshot) {
var key = rootSnapshot.key();
var childKey = rootSnapshot.val().room;
$scope.items[i].room = childKey;
});
}
It would change each of the items to have a reference to the room. Unfortunately, that list wouldn't update as the data updates, so the better solution would be to do that same query in whatever function was getting your items from the server and add the room to each item as it was being added to the items list.
To fix the issue with childKey not reading you need to use this:
var childKey = rootSnapshot.val().room;
instead of this:
var childKey = rootSnapshot.child("room").val();
console.log("room ", childKey)
Reference: https://www.firebase.com/docs/web/guide/retrieving-data.html

populate a form with a bookmarklet doesn't work in angularjs

I have a bookmarklet that just does some simple form input population but the angular form is still in an invalid state. Like nothing was ever changed.
I tried calling el.onchange() but that doesn't seem to do anything.
javascript:populate();
function populate(){
var name = document.querySelector('input[name=name]');
name.value = 'Fred';
name.click();
name.onchange();
}
Since I already have jQuery loaded, I was able to fix the issue by triggering the input event.
$('input[ng-model]').trigger('input');
I used something similar to the code below to create my bookmarklet.
Couple of things to consider.
Write your function (see example below)
Before creating your bookmarklet, test your function in the chrome console
Function tested, now remove the endlines (e.g. "replace all" in intellij (with regex enabled), replace "\n" with ""
create a new bookmark in the browser
edit the url, the url should begin with "javascript:", paste your one line url after that... you'll end up with something like "javascript:(function(){..." etc...
//nb: This function is not written to work in this page
(function () {
//get the scope object for your controller
var sc=angular.element("[ng-controller=myController]").scope();
//grab your model
var m=sc.mymodel;
//some 'dodgy' date strings :)
var today=new Date();
var todayAsString=today.toLocaleDateString("en-GB");
today.setDate(today.getDate()-183);
var sixMonthsAgoStr=today.toLocaleDateString("en-GB");
today.setDate(today.getDate()+365);
var sixMonthsLaterStr=today.toLocaleDateString("en-GB");
//pick a random oz state
var states=["WA", "VIC","SA", "NT","NSW", "ACT", "QLD"];
var ozState=states[Math.floor(Math.random()*(6)+1)];
//update the model with some semi random values
m.actionDate=todayAsString;
m.ausstralianState=ozState;
m.streetNum=Math.floor((Math.random() * 1000) + 1);
m.ID="CR" + Math.floor((Math.random() * 10000) + 1);
m.manufactureYear="" + Math.floor(Math.random()*(2016-1960+1)+1960); //approx... between 1960 and 2016...
m.endDate=sixMonthsLaterStr;
m.startDate=sixMonthsAgoStr;
//MUST call $scope.apply() at the end.
sc.$apply();
})();

Dynamic HTML error Onsen 2

My app context is generated in the run-time, on onsen 1.3 i was using this function to generate the HTML and compile it,
$scope.generateFrom = function (div) {
var el = div;
var html = HTMLGenerator.getHTML();
el.innerHTML = html;
ons.compile(el);
}
But after upgrading to onsen 2/Angular i am getting this error
"Error: First argument must be an instance of HTMLElement.
Any suggestions to fix this issue ?
As #fran-dios said on Onsen's forum, using Onsen 2.0 doesn't require you to compile elements manually. You asked for a code example of dynamically adding elements, so please see the below code to add list items to a list:
var onsItem= document.createElement('ons-list-item');
onsItem.setAttribute('modifier', "chevron");
onsItem.setAttribute('onclick', "functionName()");
onsItem.innerHTML = '<img src="" alt="something here" />';
document.getElementById('listID').appendChild(onsItem);

Resources