$ctrl in data binding is not working - angularjs

I want to make a dynamic page using angular where the user after he logged-in see his user picture and some information charged by json file throught an http request.
This is the module where i do the http requestes:
'user strict';
angular.
module('userIssue').
component('userIssue',{
templateUrl: 'user-issue/user-issue.html',
controller: 'userIssueCtrl'
})
.controller('userIssueCtrl',['$scope','$http','$routeParams',function userIssueCtrl($scope,$http,$routeParams){
var self = this;
var percorso;
$scope.utente=$routeParams.username;
document.title="Benvenuto"+" "+$routeParams.username;
$http.get('user/'+ $routeParams.username+'.json').then(function(response){
self.utenti = response.data;
});
$http.get('user/'+$routeParams.username+'.info.json').then(function(qualcosa){
self.d = qualcosa.data;
});
self.show = function(){
$scope.showForm='false';
}
}]);
and this is the part of the html page not working:
<div class="col-sm-4">
<img style="position:center;" ng-src="{{$ctrl.d.imgUrl}}" class="img-circle" alt="user image"></div>
I'm using the same approch in this part of the code:
<div class="col-md-9 col-sm-9" id="issueColumn" >
<div id="issue" ng-repeat='utenti in $ctrl.utenti'>
<li>
<dt>CODICE OPERAZIONE</dt>
<dd>{{utenti.id}}</dd>
<dt>DESCRIZIONE PROBLEMA</dt>
<dd>{{utenti.description}}</dd>
<dt>DATA SEGNALAZIONE</dt>
<dd>{{utenti.forward}}</dd>
<dt>IL PROBLEMA SARà RISOLTO ENTRO IL:</dt>
<dd>{{utenti.endstimed}}</dd>
<dt>STATO DEL PROBLEMA:</dt>
<dd>{{utenti.stato}}</dd>
</li> </br>
</div>
</div>
and here it is working! So why does the data binding not work for the image?
Could someone gently explain me why?
Here is the json file I use for the image:
[
{
"imgUrl": "img/Filippo.png",
"ciao": "ciao_calro"
}
]

As you want to use 1st element of d array object, you should be accessing 1st element of imgUrl property explicitly.
ng-src="{{$ctrl.d[0].imgUrl}}"

Hi can you try the below changes from your code and let me know,
Introduced controllerAs with the controller object:
component('userIssue',{
templateUrl: 'user-issue/user-issue.html',
controllerAs: 'userCtrl'
controller: 'userIssueCtrl' })
Accessing through the controller object name:
Try to access through the controller object name like,
{{userCtrl.d.imgUrl}} in template.

Related

ng-repeat not showing from my factory

I cannot get some data from my factory:
.factory("userDataFactory", function(){
var user;
var user_notes;
var interfaz = {
getUsuario: function(){
return user;
},
getNotes: function(){
return user_notes;
},
nuevoUsuario: function(userId, email){
user = [userId, email];
},
addNotes: function(notes){
user_notes = notes;
}
}
return interfaz;
})
What I do first is to populate the factory with data from my Ruby Api using this code:
$http({
method : "POST",
url: "http://localhost:3000/api/v1/checkuser",
data: json
}).then ( function mySucces(response){
userDataFactory.nuevoUsuario(response.data.user[0].id, response.data.user[0].email);
userDataFactory.addNotes(response.data.notes);
$state.go('thirdday');
And later on Im calling my factory in a new controller:
.controller('ListNotes', function($scope, userDataFactory, $state){
$scope.notes = userDataFactory.getNotes();
console.log($scope.notes);
//console.log($scope.notes[0].note1);
})
and finally, trying to show it in my html (listnotes.html)
<div class="list">
<a class="item" href="#" ng-repeat="x in notes">
{{ x.note2 }}
</a>
</div>
my routes config just in case:
.state('list',{
url: '/listnotes',
templateUrl: 'templates/listnotes.html',
controller: 'ListNotes'
})
so, what am I missing? why is not showing all the notes I got from the API?
Thanks in advance
EDIT
After I get the data from my API I go to 'thirdday.html' view and I just press a button to go to the list view.
.state('thirdday',{
url: '/thirdday',
templateUrl: 'templates/thirdday.html',
controller: 'Notes'
})
In your factory 'user_notes' contains object with key 'note1' (according to your log statement console.log($scope.notes[0].note1)). and in ng-repeat you are using x.note2. Make it x.note1.
try to add notes {{notes}} in html. see if it has value in there.
may be you just not add ng-app or ng-controller or someting in the mark up

html data get from $http GET is not showing properly in Angular js..?

I have defined a controller like this :
app.controller("home", function ($scope, $http, $common) {
$http({
method: "GET",
url: '/posts/loadData'
}).then(function (response) {
//console.clear()
if (typeof response.data.posts != 'undefined') {
console.log(response.data.posts);
$scope.posts = $common.arrangePosts(response.data.posts);
}
});
})
and a service to arrange data :
app.service('$common', function ($timeout, $sce, $httpParamSerializerJQLike) {
var that = this;
this.arrangePosts = function (rawPosts) {
var posts = [];
$.each(rawPosts, function (key, value) {
posts.push({
postId: value.postId,
postLink: '/post/' + that.cleanString(value.title) + '/' + value.postId,
title: value.title,
summary: $sce.trustAsHtml(value.summary)
});
});
return posts;
}
});
using values in html like this :
<div class="widget fullwidth post-single">
<h4 class="widget-title">Latest</h4>
<div class="widget-content">
<ul>
<li ng-repeat="post in posts">
<h4 class="list-title">{{post.title}}</h4>
{{post.summary}}
</li>
</ul>
</div>
</div>
Data coming from server in JSON form :
Object { postId="4", title="asdf", summary="<p>asdf</p>"}
but all the html tags are printing on my page as it is (like a text) in summary.
In many SO posts people suggested to use $sce.trustAsHtml but its not working for me. Please suggest anyway to solve my problem.
Any help will be appreciated..!!
have you tried this?
<div ng-bind-html='post.summary'></div>
You could solve this over a directive. Did you know, that you can use JQuery Lite inside AngularJS to manipulate the DOM?
Here a quick example:
angular.module("PostsDirective",[])
.directive("posts", function($sce){
return {
link: function($scope, $element, $attrs){
//the HTML you want to show
var post = "<div>hello world</div>";
var posts = [post,post,post,post];
//iterating through the list (_.each is a function from underscore.js)
_.each(posts, function(element){
//if you want to save the trusted html string in a var you can do this with getTrustedHtml
//see the docs
var safeHtml = $sce.getTrustedHtml($sce.trustAsHtml(element));
//and here you can use JQuery Lite. It appends the html string to the DOM
//$element refers to the directive element in the DOM
$element.append(safeHtml);
});
}
};
});
And the html
<posts></posts>
This also pretty nice for the readability for your HTML code. And you can use it everywhere on your page.
BTW:
As i can see, you get the HTML elements directly from a REST-Service. Why don't you get just the data and insert it into the ng-repeat? If you transfer all the HTML you get a pretty high overhead if you have loads of data.

Search Toolbar with AngularJS

This is a newbie question about Angular 1.4.
My Main Question
I have the following search view:
'use strict';
var module = angular.module('myapp.search', ['ngRoute', 'ngResource']);
module.config(function ($routeProvider) {
$routeProvider.when('/search', {
templateUrl: 'search/search.html',
controller: 'SearchCtrl'
});
});
module.factory('Search', function ($resource) {
return $resource('http://www.myapp.com/api/search', {}, {
query: {
method: 'GET',
params: {},
isArray: false
}
});
});
module.controller('SearchCtrl', function ($scope, Search) {
$scope.results = [];
$scope.query = '';
$scope.doSearch = function (query) {
Search.query({q: query}).$promise.then(function (result) {
$scope.results = result.results;
});
};
});
And the partial HTML (search.html):
#search.html
<input placeholder="search" ng-model="query" />
<button ng-click="doSearch(query)" />
<h1>Results</h1>
<ol>
<li ng-repeat="result in results">{{ result }}</li>
</ol>
...
This works perfectly, the problem is when I want to put the search input in a toolbar (defined in index.html):
#index.html
<div ng-controller="SearchCtrl">
<div class="toolbar">
<input placeholder="search" ng-model="query" />
<button ng-click="doSearch(query)">
</div>
...
In this case, by pushing the search button the query is executed in the back-end but the results are not updated in $scope. what's wrong? I've tried calling $scope.$apply() with no luck. I'm lost with this.
Bonus Question
Given that the search functionality is in the toolbar (always visible) users can execute queries in any place of the website. How can I redirect the response to http://www.myapp.com/search?
Thanks in advance.
You have two distinct instances of SearchCtrl, each with its own distinct scope: one in the navbar (dur to ng-controller="SearchCtrl"), and one in the main view (due to controller: 'SearchCtrl').
So the search in the navbar modifies the scope of the navbar controller, and the scope of the main view doesn't know anything about it.
If you want to got to the search main view when something is searched in the navbar, simply use
$location.url('/search?query=' + theEncodedQueryTypedByTheUser);
And in the search route's resolve function, or in its controller, get the route param named query, send the HTTP request, and update the scope with the results.

What can be the reason to use "controllerAs" property?

I am working on an AngularJS tutorial, and I see the following code:
.state('index',{
url:"/",
templateUrl:"views/index.html",
controller:"IndexCtrl",
controllerAs:"index"
})
What is the reason someone would want to use the controllerAs property?
Few things:
1. Reduce scope usage
Instead of loading every data in the scope of a controller, you could simply use this to load up everything that you require.
eg:
Route
state('index',{
url:"/",
templateUrl:"views/index.html",
controller:"ListCtrl",
controllerAs:"list"
})
In Controller
angular.module('feed').controller('ListCtrl', function($scope, reddit){
var vm = this;
vm.names = ["Michael", "Roy"];
});
In Template:
<ul>
<li ng-repeat="name in list.names">
<div>{{name}}</div>
</li>
</ul>
2. Correct scope usage
When multiple controllers come into play, scope becomes a tricky thing. Using controllerAs method will go a long way is resolving this. An example is shown below:
Wrong:
<span>Outside Controller: Your name is: {{username}}</span>
<div ng-controller="SignupController">
<span>Inside Controller: Your name is: {{username}}</span>
<fieldset legend="User details">
<input ng-model="username">
</fieldset>
</div>
Correct:
<span>Outside Controller: Your name is: {{user.name}}</span>
<div ng-controller="SignupController">
<span>Inside Controller: Your name is: {{user.name}}</span>
<fieldset legend="User details">
<input ng-model="user.name">
</fieldset>
</div>
Found an image which makes everthing more clear:
Courtesy : AngularJs "controller as" syntax - clarification?
Yes. A little more info:
Before the controllerAs syntax, methods and properties needed to be exposed to views by binding them to the $scope. With controllerAs, your controller instance is bound to the $scope as the property you select.
This way you can use Plain Old JavaScript Classes for your controllers.
Editorial: This is a much cleaner approach to development. One of the things that makes Angular so easy to write tests for is that your Controllers and components do not need to inherit from framework base-classes. See Backbone and Ember.
So with the old style your controllers would look like (in ES6 for simplicity):
YourController.$inject = ['$scope'];
class YourController {
constructor($scope) {
$scope.myMethod = () => { . . . };
$scope.myProperty = true;
}
}
With the controllerAs
class YourController {
constructor() {
this.myProperty = true;
}
myMethod() { . . . };
}
Just a plain old class rather than decorating or monkeypatching the $scope.
maybe you didn't googled enough!
http://toddmotto.com/digging-into-angulars-controller-as-syntax/
As the name "controllerAs" tell us, is an alias for controller them you can access your controller with that alias.
You can set your controller in many ways like :
$stateProvider.state('contacts', {
template: '<h1>{{title}}</h1>',
controller: function($scope){
$scope.title = 'My Contacts';
}
})
Or if you already have a controller defined on the module, like this:
$stateProvider.state('contacts', {
template: ...,
controller: 'ContactsCtrl'
})
Alternatively using the controllerAs syntax the above become:
$stateProvider.state('contacts', {
template: '<h1>{{contact.title}}</h1>',
controller: function(){
this.title = 'My Contacts';
},
controllerAs: 'contact'
})
and
$stateProvider.state('contacts', {
template: ...,
controller: 'ContactsCtrl as contact'
})
Or for more advanced needs you can use the controllerProvider to dynamically return a controller function or string for you:
$stateProvider.state('contacts', {
template: ...,
controllerProvider: function($stateParams) {
var ctrlName = $stateParams.type + "Controller";
return ctrlName;
}
})
Source : https://github.com/angular-ui/ui-router/wiki#controllers
Simply, Controller as syntax helps when we are working with nested controllers. The named scopes are clearly defined so there won’t be conflicts between controllers since you must state which controller you’re referencing before the dot.
<div ng-controller="Shell as shellVm">
<h1>{{shellVm.title}}</h1>
<article ng-controller="Customers as customersVm">
<h2>{{customersVm.title}} in {{shellVm.title}}</h2>
<ul ng-repeat="c in customersVm.customers">
<li>{{c.name}}</li>
</ul>
</article>
</div>
Refer AngularJs "controller as" syntax - clarification? as well.

Angularjs - Using controller

I am new to Angular.js. I currently have the following html code, where I define my div with my file html ( ng-include ) and my controller ( ng-controller ):
<div id="customerinformation-maxi" ng-include="'pages/customerinformation-maxi.html'" ng-controller="customerInformationMaxiController" class="col-md-12"></div>
This is the html code for the called html in directive ng-include ( customer-information.html ):
<div class="row">
<div class="col-md-2">
<span>Customer Number</span>
<span>{{customer.number}}</span>
</div>
<div class="col-md-2">
<span>Portfolio</span>
<span>{{custom.portfolio}}</span>
</div>
</div>
This is the js controller:
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
//Here i need to load the model variable with a literal text {{customer.number}} and {{customer.portfolio}}, how could do it? using scope object? with a json file?
});
Here I need to load the model variable with a literal text {{customer.number}} and {{customer.portfolio}}.
How could do it? Using scope object? With a json file?
Thanks for any help.
Yes, you should do it using the $scope object.
To get a general overview, here is a hello-world example:
<div ng-controller="HelloController">
{{ helloMessage }}
</div>
And in you controller's code (js file or script tag into the html):
var myApp = angular.module('myApp',[]);
myApp.controller('HelloController', ['$scope', function($scope) {
$scope.helloMessage= 'Hello World!';
}]);
But I foresee some nesting in the provided snippet of your question, so you 're probably dealing with a collection of objects which means that you have to iterate through it, in the html part, using the ng-repeat directive, like:
<tr ng-repeat="customer in customers>
<td>{{customer.number}}</td>
<td>{{customer.portfolio}}</td>
</tr>
So, your controller's functionality should contain the customers object, like:
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
var customers=[
{
number:'123',
portfolio: 'blah blah'
},
{
number:'124',
portfolio: 'blah blah'
},
{
number:'125',
portfolio: 'blah blah'
}
];
});
For further reference, you could read two respective example I have written:
Angular.js Controller Example
Angular.js JSON Fetching Example
The second one is only to see a sample usage of traversing collections, it is not meant that you have to use json, as you stated in your question; but I see that you also defined the $http service in your controller, so if it's about data that are going to be fetched from a remote destination, the JSON Fetching Example should probably help you better).
You should use scope objects to give values to your modal variables.
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
$scope.customer.number = 'sample number';
$scope.customer.portfolio = 'sample portfolio';
});

Resources