Angular JS, put json to ng-repeat out of an event fails - javascript

I am new to Angular and I have this issue that I don't get solved. I have read today alot about good style and $scope soup but I could not find an answer to this.
It is the following, very easy example:
I have a controller with an ng-repeat inside and an input with a change-event.
<div id="searchbar" data-ng-controller="SearchCtrl">
<input id="search" autocomplete="off" data-ng-model="search" data-ng-keyup="getResults( search );" />
<div id="input_results">
<li data-ng-repeat="x in names">
{{ x.Country }}
</li>
</div>
</div>
When I assign some json directly from the controller function everything works fine.
var app = angular.module("myApp", []);
var SearchCtrl = function($scope, $http, HTTPService) {
console.log("Control opened");
$scope.names = [{
"Country": "TEXT"
}];
};
When I try to assign json out of the event, then I receive there "parent is null"
var app = angular.module("myApp", []);
var SearchCtrl = function($scope, $http, HTTPService) {
var _this = this;
console.log("Control opened");
$scope.getResults = function(searchstring) {
console.log("Execute search: " + searchstring);
$scope.names = [{
"Country": "TEXT"
}];
_this.getResults(searchstring, $scope, $http);
};
};
I don't know how I can pass the correct scope to getResults() or how to solve this issue. Additionally I have read that it is best to use dots in model names like SearchStrl.search to avoid shadowing.
I am also confused about the behaviour, when I change $scope.search it works fine inside the getResult() function, but why not with the ng-repeat.
It would be nice if somebody could explain me the reason for this behaviour.
Thank you.

Your ng-repeat code fails to work because he doesn't has an array to repeat on through.the code only creates the array after you activated 'getResults' function.
in your controller you shold have something like this:
app.controller('CTRL1', function($scope){
$scope.names = [{
"Country": "TEXT"
}]; //your array
$scope.getResults = function(search) {
//your search code.
}
})
I can see you're trying to make a list of items with a search. instead of the above code I will suggest you do as followed:
<div data-ng-controller="SearchCtrl">
<input data-ng-model="search" /> <!-- creates a search instance- -->
<div id="input_results">
<!--filter by search model -->
<li data-ng-repeat="x in names | filter: search">
{{ x.Country }}
</li>
</div>
and in your code:
$scope.names = [{
"Country": "TEXT"
}];

Related

How do I use an attribute directive inside an element directive template in angularjs?

I have a need to show a list of check boxes on my site listing products and other items. The checklist-model attribute directive works well for this because I can bind it to a list of items that relates to the items selected.
All this works fine when I simply use this code in my angular controller. However, I have several list boxes that need to be displayed the same way with the same "select all" and "select none" buttons for each list. I don't want to repeat this code and layout so I've created my own directive for the entire list.
The problem is when I use my own directive it doesn't bind correctly back to my data, the select all only works once, and the select none doesn't work at all.
I suspect it has something to do with how I'm passing the scope around, and the two directives are not working well together.
Why does this not work inside a directive?
Here is a jsfiddle: https://jsfiddle.net/fande455/m9qhnr9c/7/
HTML
<section ng-app="myApp" ng-controller="couponEditController">
<script type="text/ng-template" id="checkboxlist.template.html">
<div>
<div class="form-input form-list">
<label ng-repeat="item in valuelist | orderBy:value">
<input type="checkbox" checklist-model="model" checklist-value="item" /> {{item[value]}}
<br />
</label>
</div>
<button class="btn btn-default" style="float:left; margin-bottom: 5px;margin-left: 10px;margin-right:10px" ng-click="selectNone()">Select None</button>
<button class="btn btn-default" style="float:left; margin-bottom: 5px;" ng-click="selectAll()">Select All</button>
<div class="cleared"></div>
</div>
</script>
<div>
<checkboxlist model="coupon.Products" value="Name" valuelist="productsList"></checkboxlist>
</div>
</section>
JS
var myApp = angular.module('myApp', ['checklist-model']);
myApp.directive('checkboxlist', [function() {
return {
restrict: 'E',
templateUrl: 'checkboxlist.template.html',
controller: 'checkboxlistController',
scope: {
model: "=",
value: "#",
valuelist: "="
},
require: '^checklist-model'
}
}]);
myApp.controller('checkboxlistController', ['$scope', function($scope) {
$scope.selectAll = function() {
$scope.model = angular.copy($scope.valuelist);
};
$scope.selectNone = function() {
$scope.model = [];
};
}]);
myApp.controller('couponEditController', ['$scope', function($scope) {
$scope.coupon =
{"Id": 1,
"Name": "My Coupon",
"Products": []
}
;
$scope.productsList = [{
"Id": 1,
"Name": "Product 1"
}, {
"Id": 2,
"Name": "Product 2"
}];
}]);
From documentation:
Instead of doing checklistModelList = [] it is better to do
checklistModelList.splice(0, checklistModelList.length)
In your code you should do
$scope.selectAll = function() {
$scope.selectNone();
$scope.model.push.apply($scope.model, $scope.valuelist);
};
$scope.selectNone = function() {
$scope.model.length = 0;
};
Here's the updated fiddle: https://jsfiddle.net/m9qhnr9c/9/
The idea is not to replace the array with a new one, but modify only its elements.

Retrieving JSON data from API using AngularJS

I'm trying to get data from a Web API and display it in a table, but it doesn't work.
I am new to angularjs and i code simple program to get data from the Web API and display in table.but i am not able to get data.
Module
var app = angular.module("myApp", []);
Service
app.service("myService", function ($http) {
//get All Eployee
this.getEmployees = function () {
return $http.get('http://apidemo.gouptechnologies.com/api/admin');
};
})
Controller
app.controller("myCntrl", function ($scope, myService) {
$scope.divEmployee = false;
GetAllEmployee();
function GetAllEmployee() {
alert('home');
var getData = myService.getEmployees();
getData.then(function (emp) {
$scope.employees = emp.data;
}, function () {
alert('Error in getting records');
});
}
});
The JS code is included in the head tag of the HTML file.
HTML body
<body>
<div ng-app="myApp" ng-controller="myCntrl">
<ul>
<li ng-repeat="x in employees">
{{ x.username + ', ' + x.password }}
</li>
</ul>
</div>
</body>
The API URL is legitimate.
Thanks.
Let example a json file in "data/branchList.json" directory, And i am trying to access all data from json file using $http.
It may help you to call a rest service aslo. check this example
data/branchList.json
[
{
"branch_id": 1,
"branch_name": "Mummbai",
"branch_address": "India"
},
{
"branch_id": 2,
"branch_name": "New York",
"branch_address": "US"
}
]
Controller
angular.module('myApp')
.controller('myCntrl', ['$http', '$state', function ($http, $state) {
'use strict';
var vm = this;
function init(){
vm.branchs = '';
loadBranch();
}
init();
function loadBranch(){
$http.get('data/branchList.json').success(function(response){
vm.branchs = response;
})
}
}]);
In this example i am storing all the data in vm.branches variable, you can use this variable in html page
HTML
<li class="col-sm-6" ng-repeat = "branch in vm.branchs">
<strong>{{branch.branch_name}}</strong>
<span>{{branch.branch_address}}</span>
</li>

AngularJs form not displaying form data pushed to a list

I made a simple AnguarJS app with form and list of books. In list of books I have a form, in which I can type information about book and submit, and my list of book should change. I want to make something like this: http://www.w3schools.com/angular/tryit.asp?filename=try_ng_app4
But when I add information in form, I don't see added infromatioin in book-list, but only empty field. I don't want to send information to the server, I only want to see added information on the web-page. Files, that I use are below:
app.js
var module = angular.module("sampleApp", ['ngRoute']);
module.config(function ($interpolateProvider) {
$interpolateProvider.startSymbol('[[').endSymbol(']]');
})
module.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/route1', {
templateUrl: 'static/myapp/html/test1.html',
controller: 'RouteController1'
}).
when('/route2', {
templateUrl: 'static/myapp/html/test2.html',
controller: 'BookController'
}).
otherwise({
redirectTo: '/'
});
}]);
module.controller('BookController', ['$scope', function($scope) {
$scope.books = [
{
title: 'test',
author: 'test',
}
];
$scope.addMe = function (title, author) {
$scope.books.push({title: title, author: author});
}
}]);
test2.html
<div class="container">
<div ng-controller="BookController" >
<ul>
<li ng-repeat = "book in books">
Title:<p>[[book.title]] </p>
Author: <p>[[book.author]] </p>
</li>
</ul>
<input type="text" placeholder = 'title'/>
<input type="text" placeholder = 'author'/>
<button ng-click="addMe(title,author)">Add</button>
</div>
</div>
After filling form I get the next result:
It does not work because you don't set variable.
You add title and author in addMe but if you console.log these variables, it shows undefined.
You can use $scope. You can see it as the bridge between the controller and the view. So, in your view, when you set the title and the author and click on addMe, you will get it in the controller in $scope.title and scope.author
in the view.
<input type="text" placeholder = 'title' ng-model="title"/>
<input type="text" placeholder = 'author' ng-model="author"/>
<button ng-click="addMe()">Add</button>
In the controller just after the books declaration:
$scope.title = '';
$scope.author = '';
In addMe
$scope.books.push({title: $scope.title, author: $scope.author});
Try setting $scope.books to a new array instead of pushing to it. Angular.js checks which variables have changed by comparing references. Since the variable book stays set to the same array, angular's dirty checking feature might not detect a new element.
Change it to something like this
$scope.books = $scope.books.concat([{title: title, author: author}]);
This should work because concat returns a new array instead of updating the old one.

angular ng-repeat needs changes in data that is obtained from json

I have a JSON object that does not have proper data. So i want to replace the obtained value with one from a lookup table, but I'm not sure how to replace the value of the data corresponding to the lookup table.
lookupTable = {
"pizza": function() {
console.log("food");
},
"house": function() {
console.log("building");
},
"air": function() {
console.log("nothing");
}
};
$scope.value =lookupTable["pizza"]()
my html file has
<tr ng-repeat="x in names">
<td>{{ x.lookupTable["pizza"]() }}</td>
My code is at http://plnkr.co/edit/w4lOFVRo9vSi8vqfbpXV?p=preview
Any help is appreciated!
Here are some problems in your code from the link you provided:
Functions on the lookupTable is not returning anything as pointed out in the previous answers.
lookupTable is not a property of $scope.names so using x.lookupTable is invalid.
To make it work, you should:
The functions from lookupTable should return the actual values instead of using console.log
Bind lookupTable to $scope
Use lookupTable directly inside the view as it is bound to $scope
Here is the relevant code:
<div ng-app="myApp" ng-controller="customersCtrl">
<table>
<tr ng-repeat="x in names">
<td>{{ lookupTable[x.Name]() }}</td>
</tr>
</table>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$http.get("data.json")
.then(function(response) {
$scope.names = response.data.records;
});
$scope.lookupTable = {
"pizza": function() {
return 'food';
},
"house": function() {
return 'building';
},
"air": function() {
return "nothing";
}
};
});
</script>
Your code is very confused. I tried to edit your plunker, maybe is easier to see that to explain.
<!DOCTYPE html>
<html>
<scriptsrc="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<table>
<tr ng-repeat="x in names">
<td>{{ lookupTable[x.Name] }}</td>
</tr>
</table>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$http.get("data.json")
.then(function(response) {
$scope.names = response.data.records;
});
lookupTable = {
"pizza": "food",
"house": "building",
"air": "nothing"
};
$scope.lookupTable = lookupTable;
$scope.value = lookupTable["pizza"]
console.log(lookupTable["house"])
});
</script>
Looking at your code, I am not sure what you want to achieve.
The ng-repeat gives you three objects out of names, but none of them has a lookupTable member, so {{ x.lookupTable["pizza"] }} fails silently.
You can make it visible, if you just bind to {{ x }}

updating text on view from ng-repeat

I have problem with updating view by using ng-repeat.
When click on text, it doesnt update but it overwrites below. (I want have panel with names(links) and show its description on view)
I have searched everything and couldnt find answer or something useful what would help me.
html:
<body>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<ul>
<li><a ng-repeat="item in items" ng-click="getInfo(item)" > {{item.name}} <br> </a></li>
</ul>
</div>
<hr>
<div ng-controller="myInfo">
<div ng-repeat="info in item" >
<h3>Name: {{info.name}}</h3>
<p> ID: {{info._id}}</p>
<p> temp: {{info.temp}} </p>
</div>
</div>
</div>
</body>
js
var app = angular.module('myApp', [])
app.controller('myCtrl', function($scope, $http, shareDataService) {
$http.jsonp('data.json').success(function(data) {
$scope.items = data;
});
$scope.getInfo = function(item) {
shareDataService.addItem(item);
}
});
app.controller('myInfo', function( $scope, shareDataService ){
$scope.item = shareDataService.getItem();
});
app.service('shareDataService', function() {
var myItem = [];
var addItem = function(newObj) {
myItem.push(newObj);
}
var getItem = function(){
return myItem;
}
return {
addItem: addItem,
getItem: getItem
};
});
json
angular.callbacks._0([
{
"_id": 1,
"temp": "asdgdf",
"name": "name1"
},
{
"_id": 2,
"temp": "asdasdasd",
"name": "name2"
},
{
"_id": 3,
"temp": "asasdasdadgdf",
"name": "name3"
}
]);
Plunker: http://plnkr.co/edit/X65oH0yAkRnN8npKnFY2?p=preview
You have an error in your console. Just add track by to your ng-repeat:
<div ng-repeat="info in item track by $index">
ng-repeat needs a unique id to track the items in order to be able to update them. If you add the same item twice, ng-repeat sees the same item twice, ans loses its mind. Using $index (which is unique) resolves that issue.
Keep in mind that using $index is adequate here, but it's preferred to use a unique id from the object if you can.
EDIT:
If your issue is that you want to see only the one element you clicked on in your view, then the issue is that you are adding your item to an array, when you should just be setting a value in your service. And, obviously, no need of a ng-repeat in your view.
http://plnkr.co/edit/Wfg9KhCWKMDreTFtirhR?p=preview
JS:
app.controller('myCtrl', function($scope, $http, shareDataService) {
//[...]
$scope.getInfo = function(item) {
shareDataService.setItem(item);
}
});
app.controller('myInfo', function( $scope, shareDataService ){
$scope.$watch(function () {
return shareDataService.getItem();
}, function (value) {
$scope.info = value;
})
});
app.service('shareDataService', function() {
var myItem;
return {
setItem: function(newObj) {
myItem = newObj;
},
getItem: function(){
return myItem;
}
};
});
HTML:
<div ng-controller="myInfo" ng-show="info">
<h3>Name: {{info.name}}</h3>
<p> ID: {{info._id}}</p>
<p> temp: {{info.temp}} </p>
</div>
If you only want to display information of the item that you just have clicked, then we don't need the second ng-repeat (as jlowcs said).
We also don't have to defined myItem as a array, it's just unnecessary, I think.
Edit:
how embarrassing i am, my answer look exactly to same as jlowcs's. I guess I took to much time to figure out the answer.
One thing to add up:
Why do I need a $watch in myInfo controller?
Because at the first time, we use ng-repeat, this component do the watch part for us. Then when I remove ng-repeat, I need to watch for data changing by myself.

Categories