ng-style background-image url not working for Firebase Storage reference - angularjs

I'm trying to load background images in a div. I tried several options but my page is blank, nothing is displayed. Below are the different styles I tried:
<div ng-style="{'background-image': 'url(' + profilepic + ')'}"></div>
<div ng-style="{'background-image': 'url('{{profilepic}}')'}"></div>
Where, in my controller:
storageRef.child('images/pic.png').getDownloadURL().then(function(url) {
// Get the download URL for 'images/stars.jpg'
// This can be inserted into an <img> tag
// This can also be downloaded directly
$scope.profilepic = url;
}).catch(function(error) {
// Handle any errors
});
There is no error in the console log. I get the actual url.
This works works, te image is properly displayed, but it's not what I'm trying to accomplish:
<div style="{'background-image': 'url('img/pic.png')'}"></div>
I went through similar posts and tried their solutions, but none of them seem to work.

I finally see what was the problem. I have to share this, it may help others. Everything was fine with my HTML below:
<ion-content>
<div ng-style="{'background-image': 'url('+pic+')'}">
<div class="content">
<div class="avatar" ng-style="{'background-image': 'url('+profilepic+')'}"></div>
<h3>{{fname.txt}} {{lname.txt}}</h3>
</div>
</div>
</ion-content>
The issue was within my controller. This is what I had:
auth.onAuthStateChanged(function(user) {
var storage = firebase.storage();
var storageRef = storage.ref();
var storageRefPic = '';
storageRef.child('images/pic.jpg').getDownloadURL().then(function(url) {
storageRefDefltPic = url;
}).catch(function(error) {
// Handle any errors
});
$scope.pic = storageRefDefltPic;
var storageRefProfilePic = '';
storageRef.child('images/profilepic.jpg').getDownloadURL().then(function(url) {
storageRefProfilePic = url;
}).catch(function(error) {
// Handle any errors
});
$scope.profilepic = storageRefProfilePic;
fbRef.child(userID).once('value').then(function(snapshot) {
$scope.fname.txt = snapshot.val().firstName;
$scope.lname.txt = snapshot.val().lastName;
$scope.pic = storageRefProfilePic;
});
});
My variables and code were completely mixed up. In the console, I came to realize that the firebase reference was getting called first, before the storage reference, causing my scope variables to come out empty, consequently the profile images to be blank. So I removed unnecessary variables and moved the storage references within the callback, before the data snapshot, as below:
auth.onAuthStateChanged(function(user) {
fbRef.child(userID).once('value').then(function(snapshot) {
var storage = firebase.storage();
var storageRef = storage.ref();
var storageRefPic = '';
storageRef.child('images/pic.jpg').getDownloadURL().then(function(url) {
$scope.pic = url;
}).catch(function(error) {
// Handle any errors
});
storageRef.child('images/profilepic.jpg').getDownloadURL().then(function(url) {
$scope.profilepic = url;
}).catch(function(error) {
// Handle any errors
});
$scope.fname.txt = snapshot.val().firstName;
$scope.lname.txt = snapshot.val().lastName;
});
});
Now everything is working fine! I thank you all guys for your help! I sure do appreciate you!

If I understood you correct - the problem is solved fairly easy.
You need to set the size for the div or put some content inside as background-image does not count as content.
Which leads to an empty div with height =0;
here is a working Fiddle

It should be:
<div ng-style="{'background-image': 'url({{profilepic}})'}"></div>
In your case you should use this:
<div ng-style="{'background-image': 'url(' + profilepic + ')'}"></div>
Updated JSFiddle

Related

How to call Google Cloud Endpoints with AngularJs when the page Loads, to get user information(PICTURE, NAME..)

I am trying to make a post request using Google Cloud Endpoints and AngularJS when the page loads so I can get the user information and fill the profile picture, profile description and so on...
I am able to run requests when pressing a button or something like that but can't call the google endpoints automatically when the page loads and that is whats I am trying to achieve.
Below is the HTML part where the {{userPicture}} should've been loaded in the angular script:
(HTML)
<div class="form-group">
<label class="col-sm-3 control-label">Profile image</label>
<div class="col-sm-9" ng-controller='initController'>
<img src="{{userPicture}}" class="user-image-profile" alt="User Image">
</div>
</div>
(ANGULAR)
controllers.initController = function($scope, $http){
$scope.userForm = {
"userEmail" : $.cookie('auth')
};
gapi.client.igardenendpoints.getProfile($scope.userForm).execute(function(resp) {
$scope.$apply(function () {
if (resp.error) {
$scope.backmessage.messagetext = "GetProfile Error!"
console.log("error");
} else {
if (resp.userEmail == "TEMPLATE"){
$scope.backmessage.messagetext = "Error please try again!"
}else{
$scope.userPicture = 'https://filiperebollo1986.appspot.com/serve?blob-key=' + resp.profilePicKey;
}
}
});
});
}
error
I also tried to use the following:
$scope.initData = function () {
gapi.client.igardenendpoints.getProfile($scope.userForm)...........
}
and run the function at the end of the controller, like:
$scope.initData();
But both does not work, any help on that?
I will not be able to help you in 100% as I'm not using Google Cloud, but will try to do my best.
First of all, to get the data it's usually better to use services rather than do it in the controller.
But anyway, your problem seems to be different. In your HTML did you include your script and client API?
I was able to fix my problem and bellow is the solution:
The problem was that at the moment of my call, the script may not have been loaded once I was using the "ng-app" directive directly on the body TAG.
Now I am injecting the angular module dinamicaly just after my API loading:
function googleOnLoadCallback(){
var apisToLoad = 1; // must match number of calls to gapi.client.load()
var gCallback = function() {
if (--apisToLoad == 0) {
//Manual bootstraping of the application
var $injector = angular.bootstrap(document, ['authModule']);
console.log('Angular bootstrap complete ' + gapi);
};
};
gapi.client.load('igardenendpoints', 'v12', gCallback, '//' + window.location.host + '/_ah/api');
}
</script>
<script src="https://apis.google.com/js/client.js?onload=googleOnLoadCallback"></script>
And now It is working!!!!
The only problem now is that when the page loads it appears the {{example}} in the page, is it possible to avoid the {{}} to appear?

Refresh list after server callback in AngularJS

I fetch a collection from the server and I would like to get detail for each item. All requests are received correctly, but the paragraph Loading... doesn't hide.
<h2 ng-repeat-start="server in hypervisors track by server.ip | orderBy:server.ip">
{{server.ip}}
</h2>
<div ng-repeat-end>
<p ng-hide="{{server.loaded}}" class="ng-hide">Loading...</p>
When I uncomment the line in controller before post everything works fine.
vmwareStatusApp.controller('Home', function ($scope, $http) {
$http.post('Home/ListHypervisors').success(function (data) {
$scope.hypervisors = data;
$scope.listLoaded = true;
$scope.hypervisors.forEach(function (item) {
//item.loaded = true; // this line works
$http.post('Home/HostInfo', { 'ip': item.ip }).success(function (data) {
$scope.hypervisors[0].loaded = true;
item.loaded = true;
item.detail = data;
})
.error(function(data) {
item.loaded = true;
item.error = data;
item.displayError = true;
});
});
});
});
There are many posts about refreshing view, but I haven't found any working for me. Neither anti-patter with calling $digest() didn't work, because of multiple callback. Which part of AngularJS tutorial have I skipped?
Just remove the braces from your ng-hide like this
ng-hide="server.loaded"
ng-hide and angular directives should be read like this :
ng-directive = "somethingAngularWillInterpret"
The opposite exemple is in your HTML angular will not know what he should interpret instead of just showing some text
<b>server.loaded</b> will show a bold "server.loaded"
To notice angular that he need to interpret we will use the braces
<b>{{somethingAngularWillInterpret}}</b> will show a bold result of the interpretation
EDIT :
So doing this ng-hide="{{server.loaded}}" is probably saying to angular to interpret the result of the server.loaded interpretation like a var named true or a var named false (just speculation, i need to try it).
Just tested it, this just lead to a syntax error.

Reflux store data rendering with line breaks and tag interpolation ES5

I do not want to use Babel/ES6 yet because reasons. I have been watching the egghead.io videos on react/reflux and have a component here I am rendering. It connects to the randomuser API and pulls 10 users into the store, when the store is updated it renders the user data onto the page. With the ES6 code shown in the video it allows nice interpolation of tags, so that but in my case I am just using lodash as _.map which operates slightly differently, and I am unable to find a way to render tag interpolation or even line breaks, as React renders out the elements as all children of one parent tag contained inside its own span tags.
The rendered code looks like this:
and my code is here:
var React = require('react');
var Reflux = require('reflux');
var request = require('superagent');
var _ = require('lodash');
var store = Reflux.createStore({
data: {users:[]},
init: function(){
request
.get("http://api.randomuser.me/?results=10")
.end(function(err,res){
if(err){
console.log(err)
}else {
var FirstName = res.body.results[0].user.name.first;
var LastName = res.body.results[0].user.name.last;
var picture = res.body.results[0].user.picture.thumbnail;
store.trigger({users:res.body.results})
}
});
},
getInitialState(){
return this.data;
}
});
var Name = React.createClass({
mixins:[Reflux.connect(store)],
render: function(){
return(
<div>
{_.map(this.state.users,function(n){
fName=n.user.name.first
lName=n.user.name.last
picture = n.user.picture.thumbnail;
return ""+fName+" "+lName + " " + picture
})
}
</div>
)
}
});
React.render(<Name />, document.getElementById('users'));
Any suggestions or advice would be greatly appreciated! also the egghead.io videos are top notch, i must give credit where it is due!
Personally, I try to avoid doing interpolation in JSX tags. JSX gives you a pretty solid API for constructing DOM elements! In this case, I'd do something like this:
render: function() {
var userElements = _.map(this.state.users,function(n){
var fName=n.user.name.first
var lName=n.user.name.last
var pictureURL = n.user.picture.thumbnail;
return (
<div className='user'>
<span className='first-name'>{fname}</span>
<span className='last-name'>{lname}</span>
<img className='picture' src={pictureURL}></img>
</div>
)
})
return (
<div className='user-container'>
{userElements}
</div>
)
}

Marionette layout view -- why is a template necessary

In spite of reading the marionette docs several times over, I am still not able to fully comprehend some aspects of it correctly.
I am creating a layout view 'AppLayout' as below:
var AppLayoutView = Marionette.LayoutView.extend({
regions: {
headerRegion: "#ecp_header",
bodyRegion: "#ecp_layout_region"
},
...
The html snippet for my app is having the two dom nodes for above defined regions:
<div id="ecp_header"></div>
<div class="container" id="ecp_layout_region">
<div class="row" id="ecp_body">
...
in app.js, my calling code is like this..
ECPApp.on('start', function() {
require(['controller_cp', 'header_view'], function(ControllerCP, HeaderView) {
console.log("On start event executing...");
// create a event aggregator vent object and attach to app.
ECPApp.vent = new Backbone.Wreqr.EventAggregator();
var appLayoutView = new AppLayoutView();
appLayoutView.render();
//appLayoutView.showLayout();
//$('div.toolbar > ul > li:first > a').tab('show');
if (Backbone.history) Backbone.history.start();
});
This gives me error Cannot render the template since it is null or undefined.
I thought that the default render() behavior of layout always looks for a template, so I rolled out my own version of render, as below:
render: function() {
var $self = this;
/* if no session exists, show welcome page */
var promise = ECPApp.request('entities:session');
promise.done(function(data) {
if (data.result==0) {
console.log('Valid session exists. Showing home page...!');
$self.showHome();
} else {
console.log('No session exists. Showing welcome page...!');
$self.showWelcome();
}
}).fail(function(status) {
console.log('No session exists. Showing welcome page...!');
$self.showWelcome();
});
return $self;
},
showWelcome: function() {
var self = this;
require(['header_view', 'welcome_view'],
function(HeaderView, WelcomeView) {
var headerView = new HeaderView();
var welcomeView = new WelcomeView();
self.bodyRegion.show(welcomeView);
});
}
This time, I get another error saying, An "el" #ecp_layout_region must exist in DOM. However I am sure that the element is existing in the DOM, as I can see it by checking in the debug console window. Running $('#ecp_layout_region') shows a valid element.
Marionette layout view is pretty confusing. Going forward I need multiple nested views. I am stuck here.
How is your template located? Is your template wrapped by <script type = “text/template”> tag?
It may look like this:
Inside your html, in head section:
<script type = “text/template” id="yourLayout">
<div id="ecp_header"></div>
<div class="container" id="ecp_layout_region">...</div>
</script>
And in Layout definition:
var AppLayoutView = Marionette.LayoutView.extend({
template: '#yourLayout'
...
});

Making body class the url of the page without the first forward slash

I am having trouble trying to get Angular to spit out the url of the page in to the page class each time the navigation changes the page. This is what I have so far:
$scope.currentPage = getCurrentPage;
var getCurrentPage = function () {
var login = 'login';
var url = $location.url().substring(1);
if (url = null || url = undefined) {
return login;
} else {
return url;
}
};
I have this on the content wrapping <div>:
<div class="" ng-controller="AppCtrl" ng-class="currentPage + 'Page'"></div>
Any hardcore Angulars out there? Please help.
JP
A few things to do differently:
I don't think the function is actually getting called, so:
$scope.currentPage = getCurrentPage();
$scope.currentPage += "Page"; // just keeping the concatenation out of the markup
EDIT: I think I'm wrong about the above statement. I'm still fuzzy on when to call() vs reference the function in situations like this...
Also, this line needs some retouching of the operators:
if (url == null || url === undefined);
And, I am not sure ng-class is entirely necessary in this case. It is usually used to evaluate an expression. I would simply use:
<div class="" ng-controller="AppCtrl" class="{{currentPage}}"></div>
Hopefully someone else can verify me on all of these points, as I am fairly new to JS and AngularJS.
For anyone who comes across this and would like a more verbose answer, here you go!
In view:
<div class="" ng-controller="AppCtrl" class="currentPage"></div>
In controller:
$scope.$watch(function () {return $location.url();}, function () {
var getCurrentPage = function () {
var login = 'loginPage';
var currentUrl = $location.url().substring(1);
if (currentUrl === '' || currentUrl === undefined) {
return login;
} else {
return currentUrl + 'Page';
}
};
$scope.currentPage = getCurrentPage();
console.log($scope.currentPage);
});

Resources