Angular returns [object Object] - angularjs

my Angular code returns [object Object]. I am calling 2 controllers on different pages. First one sets the data on ng-click and the second one gets (displays) the data. Here is the code:
Angular App code:
var careerApp = angular.module("careerApp", []);
careerApp.factory('myService', function () {
var savedData = {};
function set(data) {
savedData = data;
}
function get() {
return savedData;
}
return {
set: set,
get: get
}
});
careerApp.controller("JobList", function ($scope,myService) {
myService.set(data);
});
careerApp.controller("JobSelection", function ($scope, myService) {
$scope.jobname = myService.get();
});
HTML on Page 1
<div class="center-details" ng-controller="JobList">
<div class="details" ng-click="set(data)" >
<h2 class="name" ng-model="jobtitle">
Winter
</h2>
<p><b>Job ID#</b> <span class="jobid">2017-01</span></p>
</div>
</div>
HTML on Page 2
<div ng-controller="JobSelection">
<label ng-bind="jobname"></label>
</div>

You are bringing the whole object in
<label ng-bind="jobname"></label>
If you intented to write the object with a better formatting try changing it to:
<label> {{ jobname | json }}</label>
This way it will be formatted and printed as a json object.

Use Angular expressions intead of ng-bind. Otherwise you will have to specify a specific property of your object.
page 1
<div class="center-details" ng-controller="JobList">
<div class="details" ng-click="set('Winter')" >
<h2 class="name">
Winter
</h2>
<p><b>Job ID#</b> <span class="jobid">2017-01</span></p>
</div>
</div>
Controller:
careerApp.controller("JobList", function ($scope,myService) {
$scope.set= function(data){
myService.set(data);
}
});
page 2
<label ng-bind="jobname"></label>
<label>{{jobname}}</label>
How to make it dynamically, based on the input
<input stype="text" ng-model="jobTitle" ng-change="set()" >
<h2 class="name">
{{jobTitle}}
</h2>
Controller:
careerApp.controller("JobList", function ($scope,myService) {
$scope.jobTitle = "";
//This function will be called every time that jobTitle change its value.
$scope.set= function(){
myService.set($scope.jobTitle);
}
});
Notes:
Take into account that ng-model directive binds an input, select, textarea value to a property on the scope.
Since you have this assignment in your controller definition
$scope.jobname = myService.get();
If you run this controller before the user make a click it will be empty. it wont be refreshed in every click.

Related

Second instance of angular controller does not display declared variables

I have a page that has two instances of the same controller, the first one is loaded with the page and the second comes from an ajax request. Inside the controller I have a variable called filter, with initial value equal to "status". When I try to display this variable in the first instance it displays correctly. But when I show this variable in the second instance it looks undefined, it shows Filter: # {{mClerk.filter}}. The changeFilter function works in both instances.
My controller
app.controller('clerkCtrl', function ($scope, $http, $compile, $timeout, notifyService, DTOptionsBuilder, DTColumnBuilder) {
this.filter = 'status';
this.changeFilter = function (filter) {
this.filter = filter;
};
});
First Instance,
<div ng-controller="clerkCtrl as Clerk">
Filter: #{{Clerk.filter}} <!-- OK -->
<div class="card">
<div class="card-header">
<h2><i class="zmdi zmdi-accounts-list zmdi-hc-fw"></i> Lista</h2>
</div>
<div style="padding: 0px 20px;">
<div class="card-body table-responsive">
<table datatable="" dt-options="Clerk.dtOptions" dt-columns="Clerk.dtColumns"
class="table table-striped"></table>
</div>
</div>
</div>
</div>
Second instance, from a ajax request:
<div ng-controller="clerkCtrl as mClerk">
Filtro: #{{mClerk.filter}} <!-- FAILED -->
<button ng-click="mClerk.changeFilter('date')">Change filter</button>
</div>
Function that brings the page to the second instance,
$scope.loadPage = function (page) {
$http.post(page, [], $scope.config)
.then(function (response) {
$scope.modal.body = $sce.trustAsHtml(response.data.body);
$scope.modal.title = $sce.trustAsHtml(response.data.title);
$('#modalx').modal('show');
$scope.reloadPlugins();
setTimeout(function () {
$compile(angular.element('.modal-body').contents())($scope);
}, 0);
});
};

ng-click inside ng-repeat doesnt work

I have html which looks like one below, I have 2x ng-click in whole code in both situation I call same function. Both functions are in same controller.
<div class="tagselect tagselect--frameless">
<div class="combobox__body combobox__body--open combobox__body--frameless" ng-show="focus">
<ul class="list-unstyled">
<li class="combobox__item" ng-repeat="pos in listCtrl.positions | filter:query as results"
ng-click="listCtrl.choosePosition(pos)">{{pos.name}}
</li>
</ul>
</div>
</div>
<div class="col-md-2 no-padding">
<button type="button" class="btn btn-success" ng-click="listCtrl.chosenPositions(789456)">Add</button>
</div>
controller looks like:
myApp.controller('ListCtrl', ['$scope', '$cookies', '$http', function ($scope, $cookies, $http) {
var listCtrl = {
candidates: [],
positions: [],
chosenPositions: [],
init: function () {
listCtrl.getCandidates();
listCtrl.getPositions();
},
getCandidates: function () {
$http.get('candidates.json').then(function (res) {
listCtrl.candidates = res.data;
});
},
getPositions: function () {
$http.get('positions.json').then(function (res) {
listCtrl.positions = res.data;
});
},
choosePosition: function (position) {
console.log(position);
}
};
listCtrl.init();
$scope.listCtrl = listCtrl;
}]);
I double check for missspells and make sure its not because of function (I create a new one with simple console log).
Problem is that button click correctly call function but ng-repeat <li ng-click=""> doesnt do anything. I read in angular documentation that ng-repeat create new scope but this should be still okey in my opinion as soon as I use reference to object listCtrlchoosePosition()
Can someone tell me what I am doing wrong?
Thanks
EDIT: Plunker example:
http://plnkr.co/edit/ooUQA2n1Vyj8RZtsQ1Pj?p=preview
ng-blur is doing something weird, so I'm going to suggest you to change the $scope.focus value from the ListCtrl instead of using the ng-blur.
html file
<!-- more html code -->
<!-- input without ng-blur directive -->
<input class="tagselect__input" placeholder="Position" ng-focus="focus=true" ng-model="query">
<!-- more html code -->
<li class="combobox__item" ng-repeat="pos in listCtrl.positions | filter:query as results" ng-click="listCtrl.choosePosition(pos)">{{pos.name}}
<!-- more html code -->
js file
// more code goes here.
choosePosition: function (position) {
//alert('Going to choosen position');
//$scope.query = position.name;
$scope.focus = false; // Hide div options from here.
// rest of your code.
},
// more code goes here.
Working in this plunkr

Test if an object is an empty object in a AngularJS template

I have a simple object in a controller which can sometimes be empty ({}).
app.controller('TestController', function() {
var vm = this;
vm.testObject = {};
});
I want to hide or show some DOM-elements in the corresponding template when the object is empty or not.
I tried to do it with a simple <div ng-if="vm.testObject"> but when vm.testObject === {} it is considered true in the ng-if.
<div ng-controller="TestController as vm">
<div ng-if="vm.testObject">
Test Object is not empty
</div>
<div ng-if="!vm.testObject">
Test Object is empty
</div>
</div>
Is there a simple way to check for an empty object in the template? Preferably without adding new variables to the scope.
Here is a working Plunker:
http://plnkr.co/edit/Qed2MKmuedcktGGqUNi0?p=preview
You should use an AngularJs filter:
Javascript:
app.filter('isEmpty', [function() {
return function(object) {
return angular.equals({}, object);
}
}])
Html template:
<div ng-if="!(vm.testObject | isEmpty)">
Test Object is not empty
</div>
<div ng-if="vm.testObject | isEmpty">
Test Object is empty
</div>
Updated plunkr: http://plnkr.co/edit/J6H8VzUKnsNv1vSsRLfB?p=preview
Are you ok with moving the equality check to the ng-if?
<div ng-controller="TestController as vm">
<div ng-if="!equals({}, vm.testObject)">
Test Object is not empty
</div>
<div ng-if="equals({}, vm.testObject)">
Test Object is empty
</div>
</div>
Otherwise, provide a helper on the scope
app.controller('TestController', function() {
var vm = this;
vm.testObject = {};
vm.empty = function() {
return vm.testObject === {};
};
});
then
<div ng-controller="TestController as vm">
<div ng-if="!vm.empty()">
Test Object is not empty
</div>
<div ng-if="vm.empty()">
Test Object is empty
</div>
</div>
This is an old thread but I find easier to check if the Object has keys.
<div ng-controller="TestController as vm">
<div ng-if="Object.keys(vm.testObject).length">
Test Object is not empty
</div>
<div ng-if="!Object.keys(vm.testObject).length">
Test Object is empty
</div>
</div>
It's simple and readable.
This will work. check the Length
<div ng-if="!!vm.testObject && vm.testObject.length > 0">
Test Object is not empty
</div>
You can convert the object to a JSON string using the built-in AngularJS json filter and do a comparison like this:
<div ng-if="vm.testObject | json) != '{}'">
Test Object is not empty
</div>

Can not get the scope variable properly

I have a simple text box and a button and whenever user click on button the alert shows the text of textbox but I want to do it this way(I know there are a lot better ways but first I want to understand why this way does not work):
var app = angular.module('app', []);
app.factory('Service', function() {
var service = {
add: add
};
return service;
function add($scope) {
alert($scope.user.username);
}
});
app.controller('table', function(Service,$scope) {
//get the return data from getData funtion in factory
this.add = Service.add($scope);
});
As you can see I send the scope to factory and I define the user.username as follow:
<button class="btn btn-primary" ng-click="t.add(user.userName)">
But when I run this nothing happens can anyone tell me what is wrong with this code?
<body ng-app="app">
<form>
<div class="row commonRow" ng-controller="table as t">
<div class="col-xs-1 text-right">item:</div>
<div class="col-lg-6 text-right">
<input id="txt" type="text" style="width: 100%;"
ng-model="user.userName">
</div>
<div class="col-xs-2">
<button class="btn btn-primary" ng-click="t.add(user.userName)">
click me</button>
</div>
</div>
</form>
also the plnk link is as follow:
plnkr
The problem is in this line
this.add = Service.add($scope);
Here you are assigning the returned (which is undefined) value of the Service.add($scope) invocation to the this.add.
The right approach will be either
this.add = function(data) { Service.add($scope); }
or
this.add = Service.add;
// in the service factory.
function add(usrNm) {
alert(usrNm);
}
The first thing is you can't use $scope in a service.and in controller your not assaining this(object) to $scope.so $scope doesn't contain any value.
I suppose you to write like this
$scope.user = this;

Use an Angular directive to generate html from an array

I'm trying to use an Angular directive to create a form where the user can specify the number of children and, for each child, an edit box appears allowing the childs date of birth to be entered.
Here's my HTML:
<div ng-app>
<div ng-controller="KidCtrl">
<form>
How many children:<input ng-model="numChildren" ng-change="onChange()"/><br/>
<ul>
<li ng-repeat="child in children">
<child-dob></child-dob>
</li>
</ul>
</form>
</div>
</div>
Here's the JS:
var app=angular.module('myApp', []);
function KidCtrl($scope) {
$scope.numChildren = 2
$scope.children = [{dob: "1/1/90"}, {dob: "1/1/95"}];
$scope.onChange = function () {
$scope.children.length = $scope.numChildren;
}
}
app.directive('childDob', function() {
return {
restrict: 'E',
template: 'Child {{$index+1}} - date of birth: <input ng-model="child.dob" required/>'
};
});
And here's a jsFiddle
The problem is that it's just not working.
If I enter 1 in the numChildren field then it shows 1 bullet point for the list element but it doesn't show any of the HTML.
If I enter 2 in the numChildren field then it doesn't show any list elements.
Can anyone explain what I'm doing wrong?
Many thanks ...
Your main issue is that the directive childDOB is never rendered. Even though your controller works because 1.2.x version of angular has global controller discover on. It will look for any public constructors in the global scope to match the controller name in the ng-controller directive. It does not happen for directive. So the absence of ng-app="appname" there is no way the directive gets rendered. So add the appname ng-app="myApp" and see it working. It is also a good practice not to pollute global scope and register controller properly with controller() constructor. (Global look up has anyways been deprecated as of 1.3.x and can only be turned off at global level.)
You would also need to add track by in ng-repeat due to the repeater that can occur due to increasing the length of the array based on textbox value. It can result in multiple array values to be undefined resulting in duplicate. SO:-
ng-repeat="child in children track by $index"
Fiddle
Html
<div ng-app="myApp">
<div ng-controller="KidCtrl">
<form>How many children:
<input ng-model="numChildren" ng-change="onChange()" />
<br/>
<ul>
<li ng-repeat="child in children track by $index">{{$index}}
<child-dob></child-dob>
</li>
</ul>
</form>
</div>
</div>
Script
(function () {
var app = angular.module('myApp', []);
app.controller('KidCtrl', KidCtrl);
KidCtrl.$inject = ['$scope'];
function KidCtrl($scope) {
$scope.numChildren = 2
$scope.children = [{
dob: "1/1/1990"
}, {
dob: "1/1/1995"
}];
$scope.onChange = function () {
$scope.children.length = $scope.numChildren;
}
}
app.directive('childDob', function () {
return {
restrict: 'E',
template: 'Child {{$index+1}} - date of birth: <input ng-model="child.dob" required/>'
}
});
})();

Resources