Ng-repeat functionality doesnt work - javascript

Today is my first day with Angular.js , and I stuck at a basic controller :
my APP.js
(function()
{ var app = angular.module('store', [ ] );
app.controller('StoreController', function()
{
this.product = gem;
});
var gem = [
{name:'John', price:25, description:'boy',soldout: false,canpurchase:true},
{name:'Kohn', price:25, description:'boy',soldout: false,canpurchase:true}
]
//not mentioned:false
})();
Index.HTML
<!DOCTYPE html>
<html ng-app="store">
<script src="js/angular.min.js" type="text/javascript"></script>
<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<title>Purple</title>
</head>
<body ng-controller = "StoreController as store">
<script src="js/app.js" type="text/javascript"></script>
<h1>{{"Create your CV"}}</h1>
<div ng-repeat="products in store.product">
<div ng-hide="store.product.soldout">
<h1> {{store.product.name}} </h1>
<h2><em class="pull-right">{{store.product.price | currency}}</em></h2>
<h3> {{store.product.description}} </h3>
<button ng-show = "store.product.canpurchase"> Add to cart </button>
</div>
</div></body></html>
My code is working fine , but NG - repeat is not working, if I don't choose ng-repeat and display each item as an array then I am getting a display but not with "ng-repeat" .. Any idea's what am I missing ?
Please dont mark this as negative, I have done a lot of research before asking this question
Code on fiddle : http://jsfiddle.net/68Dkz/2/

Here is working version using controller alias store as shown. Note that product was changed to products in controller since the array contains more than one product. I think you are gtting confused about which is array and which is the individual item within the ng-repeat due to this
<div ng-repeat="product in store.products">
<div ng-hide="product.soldout">
<h1> {{product.name}} </h1>
<h2><em class="pull-right">{{store.product.price | currency}}</em></h2>
<h3> {{product.description}} </h3>
<button ng-show="product.canpurchase">Add to cart</button>
</div>
</div>
DEMO

store is your module not your scope you don't need it in the iteration, do products in product instead
<div ng-repeat="products in product">
<div ng-hide="products.soldout">
<h1> {{products.name}} </h1>
<h2><em class="pull-right">{{products.price | currency}}</em></h2>
<h3> {{products.description}} </h3>
<button ng-show = "products.canpurchase"> Add to cart </button>
</div>
</div>
stop aliasing your controller, it is unnecessary and may cause issues with the html compiler
using products as your iterator is confusing, I would suggest making the collection products and the iterator product

Related

Angular Js Show the Checkbox's Checked when Page Loads

Angular Js Show the Checkbox's Checked when Page Loads.
I am saving the Checkboxes. when I Reload the Page I want to show the selected checkboxes
<md-checkbox ng-repeat="primaryPrograms in ctrl.primaryProgramStudies" ng-model="ctrl.primaryProgramStudiesSelected[primaryPrograms.id]" ng-checked="primaryPrograms.selected==true">
{{primaryPrograms.name}}
</md-checkbox>
Script :
ctrl.primaryProgramStudiesSelected =
[{"id":1,"name":"SAT","selected":false},{"id":2,"name":"ACT","selected":true},{"id":3,"name":"PSAT","selected":false},{"id":4,"name":"ISEE\/SSAT","selected":false},{"id":5,"name":"AP","selected":true},{"id":6,"name":"General GPA Management","selected":true},{"id":7,"name":"Reading","selected":false},{"id":8,"name":"Math","selected":false},{"id":9,"name":"Science","selected":false},{"id":10,"name":"Social Studies","selected":false},{"id":11,"name":"ESL","selected":true},{"id":12,"name":"College Admissions","selected":true},{"id":13,"name":"TOEFL ","selected":false}]]`
ngChecked directive should not be used together with ngModel, as this can lead to unexpected behavior.
https://docs.angularjs.org/api/ng/directive/ngChecked
angular.module('MyApp',['ngMaterial', 'ngMessages'])
.controller('AppCtrl', function($scope) {
$scope.items = [{"id":1,"name":"SAT","selected":false},{"id":2,"name":"ACT","selected":true},{"id":3,"name":"PSAT","selected":false},{"id":4,"name":"ISEE\/SSAT","selected":false},{"id":5,"name":"AP","selected":true},{"id":6,"name":"General GPA Management","selected":true},{"id":7,"name":"Reading","selected":false},{"id":8,"name":"Math","selected":false},{"id":9,"name":"Science","selected":false},{"id":10,"name":"Social Studies","selected":false},{"id":11,"name":"ESL","selected":true},{"id":12,"name":"College Admissions","selected":true},{"id":13,"name":"TOEFL ","selected":false}];
});
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-sanitize.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="AppCtrl" class="md-padding demo checkboxdemoSelectAll">
<div layout="row" layout-wrap="">
<div flex="100" layout="column">
<div>
<fieldset class="demo-fieldset">
<legend class="demo-legend">Select </legend>
<div layout="row" layout-wrap="" flex="">
<div class="demo-select-all-checkboxes" flex="100">
<md-checkbox ng-repeat="item in items" ng-model="item.selected">
{{ item }}
</md-checkbox>
</div>
</div>
</fieldset>
</div>
</div>
</div></div>
</div>
While reload the app, Everything reload & the code is render freshly. And whatever changes made in client side(without server side), everything gone.
So as per #Pengyy comment you have to store the selected items to server / cookies / localstorage. Then when reload pages just read the stored data and reset check boxes.
Change ng-model="ctrl.primaryProgramStudiesSelected[primaryPrograms.id]" to ng-model="ctrl.primaryProgramStudiesSelected[primaryPrograms.selected]".
Then add selected property to every object in your primaryProgramStudiesSelected array. If you want it to be selected by default, make the selected property true.
Can you try something like this:
<div ng-repeat="primaryPrograms in ctrl.primaryProgramStudies">
<div class="checkbox">
<label>
<input ng-model="primaryPrograms.selected" ng-true-value="true" ng-false-value="false" type="checkbox" ng-checked="primaryPrograms.selected === true"> Checked
</label>
</div>
</div>
Note: if you are using mysql your true/false fields are probably tiny int, and you should use ng-true-value="1" ng-false-value="0".
Also note that in controller you already should set selected to true, im not sure how you get your data and how you know if field is selected. But this example should work.

AngularJS advice on how to fix a bug when pushing two of the same strings into the array

I'm having trouble trying to figure out how to fix a bug that happens when I try to push the same string as added previously to the array. It gets stuck and will not allow the app to post another string.
How do I make sure that your repeat doesn't get stuck when there two of the same values in the array?
Bug Example Screenshot
--> Bug happens when I try to push "1"into the array again after a "1" is already posted.
HTML Code
<body>
<div data-ng-controller="appController" class="container">
<div class="row">
<form>
<label for = "status"> Status: </label>
<input data-ng-model = "input_data" type="text" id="status"/>
<button data-ng-click="add_data()"> OK </button>
<ul class = "list-group">
<li class="list-group-item" data-ng-repeat="x in array_data">
{{x}}
<button data-ng-click = "remove_data($index)">DEL</button>
</li>
</ul>
</form>
</div>
</div>
<script src="framework/js/jquery.min.js"></script>
<!-- All Bootstrap plug-ins file -->
<script src="framework/js/bootstrap.min.js"></script>
<!-- Basic AngularJS -->
<script src="framework/js/angular.min.js"></script>
<!-- Your Controller -->
<script src="framework/js/appstatpost.js"></script>
</body>
AngularJS code
var app = angular.module("myApp", []);
app.controller("appController", function ($scope) {
$scope.array_data = [];
$scope.add_data = function () {
$scope.array_data.push($scope.input_data);
};
$scope.remove_data = function (index) {
$scope.array_data.splice(index, 1);
};
});
You could use track by $index, example:
<li class="list-group-item" data-ng-repeat="x in array_data track by $index">
AngularJS tries by default to find a key in your array to index by. Normally this works well, but if you have duplicates then you have to tell AngularJS to make a new index, in this case, $index.

Using ng-if to check angular variable from another directive in angularjs

I am new to angular. I have a task to display json data in specific design, but I have not idea about nesting of json. Is it possible to check if the data is json or an array of json and then display the output.
Here I am trying to display data only if it is an array. But it is not working. Kindly help.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp">
<div ng-controller="readJson as rj">
<div ng-repeat="d in rj.data">
<ul>
<div ng-model="myVar" ng-init="myVar = "{{isArray(d.third)}}>
<div ng-if="myVar">
<li>{{d.third}}</li>
</div>
</ul>
</div>
</div>
</div>
</body>
<script>
(function(){
var app=angular.module('myApp',[]);
app.controller('readJson',function($scope){
$scope.isArray = angular.isArray;
this.data=[{"first":"one","second":"two","third":"three"},
{"first":"ONE","second":"two","third":"three"},
{"first":"onE","second":"two","third":
[
{"first":"1one","second":"2two","third":"3three"},
{"first":"1ONE","second":"2two","third":"3three"}
]}];
});
})();
</script>
</html>
Here you go. This example will display data only when "third" param is an array.
https://plnkr.co/edit/EX0BvcYrLPFbiN2ezlqQ
<div ng-repeat="d in data">
<ul>
<div ng-init="myVar = isArray(d.third)"></div>
<div ng-if="myVar">
<li>{{d.third}}</li>
</div>
</ul>
</div>
The problem was in ng-init="myVar = "{{isArray(d.third)}} - you need to make sure isArray(d.third) is in expression (between "") and there is no need to use {{}} syntax within ng-init directive. It will evaluate expression for you (check an example).

Combining results from WP-API using AngularJS

I currently have this site - http://dev.5874.co.uk/scd-data/ where I have a dropdown which displays results from WP-API which I am pulling in through AngularJS.
It currently combines the two sets of results as they're separate URL's, the results are in categories within a custom post type so if both posts are 'tagged' in the same category chosen they display twice. I need a way to combine the two sets of results but only showing one of the posts - I hope this makes sense. I'm very new to API data and AngularJS and I imagine there is a much simpler way of doing this. Any help would be much appreciated. Here is a snippet of my code to show how it's currently working.
Thanks in advance!
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<style>
.desc {display: none;}
</style>
<script type="text/javascript">
$(function(){
$('.selectOption').change(function(){
var selected = $(this).find(':selected').text();
//alert(selected);
$(".desc").hide();
$('#' + selected).show();
}).change()
});
</script>
<script>
var app = angular.module('myApp', []);
app.controller('northWestCtrl', function($scope, $http) {
var url = 'http://scd.blaze.wpengine.com/wp-json/posts?type=listings&filter[listing_area]=northwest';
$http.get(url).then(function(data) {
$scope.data = data.data;
});
});
</script>
<select class="selectOption">
<option>Search by Region</option>
<option>NorthWest</option>
<option>NorthEast</option>
<option>Midlands</option>
<option>EastAnglia</option>
<option>SouthEast</option>
<option>SouthWest</option>
<option>Scotland</option>
<option>Wales</option>
<option>NorthernIreland</option>
<option>ChannelIslands</option>
</select>
<div id="changingArea">
<body ng-app="myApp">
<div id="NorthWest" class="desc">
<div ng-controller="northWestCtrl">
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<img src="{{d.acf.logo}}">
<div id="listing-contact">Contact: {{d.acf.contact}}, {{d.acf.position}}</div>
<div id="listing-address-1">
{{d.acf.address_1}}, {{d.acf.address_2}} {{d.acf.address_3}} {{d.acf.town}} {{d.acf.county}} {{d.acf.postcode}}
</div>
<div id="listing-phone">Telephone: {{d.acf.telephone}}</div>
<div id="listing-mobile">Mobile: {{d.acf.mobile}}</div>
<div id="listing-email">Email: {{d.acf.email}}</div>
<div id="listing-website">Website: {{d.acf.website}}</div>
<div id="listing-established">Established: {{d.acf.established}}</div>
<div id="listing-about">About: {{d.acf.about}}</div>
<div id="listing-mailingaddress">Mailing Address: {{d.acf.mailing_address_}}, {{d.acf.mailing_address_2}}, {{d.acf.mailing_address_3}}, {{d.acf.mailing_town}}, {{d.acf.mailing_county}}, {{d.acf.mailing_postcode}}</div>
<div id="listing-directions">Directions: {{d.acf.directions}}</div>
<div id="scd-link">View on The Shooting Club Directory</div>
</div>
</div>
</div>
</body>
</div>
Here is a working code pen - http://codepen.io/anon/pen/yePYdq
Angular is a great JavaScript front-end framework to choose, and you're off to a good start, but a lot of changes could be made. I've made some suggested changes for easier ways to do things below.
See this CodePen for all changes.
It looks like you've grasped the idea of ng-repeat, but there's definitely a lot of repeated HTML and JS in your view and controller, so let's see if we can do better.
Let's try this without jQuery to avoid direct manipulation of the DOM. And instead of many controllers, we can do this with a single controller.
<div ng-app="MyApp">
<div ng-controller="MyController">
...
</div>
</div>
<script type="text/javascript">
var app = angular.module('MyApp', []);
app.controller('MyController', ...);
</script>
For the dropdown, we'll use ng-repeat in our view and display the names of the shooting types from our model
...
<select ng-model="selectedListing">
<option
ng-repeat="listingShootingType in listingShootingTypes"
value="{{listingShootingType.name}}">
{{listingShootingType.name}}
</option>
</select>
...
<script type="text/javascript">
...
// Our selections/filters
$scope.listingShootingTypes = [
'All',
'Air Rifle/Air Pistol',
'Clay',
'ABT',
'Double Trap',
'English Skeet',
'English Sporting',
'Fitasc',
'Olympic Skeet',
'Olympic Trap',
'Simulated Game',
'Sport Trap/Compact',
'Universal Trench',
'ZZ/Helice',
'Rifle',
'Centrefire Target Rifle',
'Gallery Rifle',
'Muzzle Loading',
'Practice Shotgun',
'Smallbore Rifle'
];
...
</script>
With only one controller, we can still use ng-repeat for each listing.
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<div id="listing-image"><img src="{{d.acf.logo}}"></div>
<div id="listing-contact">Contact: {{d.acf.contact}}, {{d.acf.position}}</div>
<div id="listing-address-1">
{{d.acf.address_1}}, {{d.acf.address_2}} {{d.acf.address_3}} {{d.acf.town}} {{d.acf.county}} {{d.acf.postcode}}
</div>
<div id="listing-phone">Telephone: {{d.acf.telephone}}</div>
<div id="listing-mobile">Mobile: {{d.acf.mobile}}</div>
<div id="listing-email">Email: {{d.acf.email}}</div>
<div id="listing-website">Website: {{d.acf.website}}</div>
<div id="listing-established">Established: {{d.acf.established}}</div>
<div id="listing-about">About: {{d.acf.about}}</div>
<div id="listing-mailingaddress">Mailing Address: {{d.acf.mailing_address_}}, {{d.acf.mailing_address_2}}, {{d.acf.mailing_address_3}}, {{d.acf.mailing_town}}, {{d.acf.mailing_county}}, {{d.acf.mailing_postcode}}</div>
<div id="listing-directions">Directions: {{d.acf.directions}}</div>
<div id="scd-link">View on The Shooting Club Directory</div>
</div>
Finally... How do we only display listings that match our selected shooting type from the dropdown? We could use a custom Angular filter!
...
<div ng-repeat="d in data | filter:isSelectedListing">
...
<script type="text/javascript">
...
// Let's define a custom Angular filter because the WordPress JSON is complex
$scope.isSelectedListing = function(listing) {
// Show nothing if nothing is selected
if (angular.isUndefined($scope.selectedListing) || $scope.selectedListing == '') {
return false;
}
// Show all if 'All' is selected
if ($scope.selectedListing == 'All') {
return true;
}
// If the shooting type we're looking for is present, show the listing.
// To do this, we parse the WordPress JSON object model.
if (angular.isDefined(listing.terms.listing_shooting_type)) {
for (var i = 0; i < listing.terms.listing_shooting_type.length; i++) {
if (listing.terms.listing_shooting_type[i].name == $scope.selectedListing) {
return true;
}
}
}
return false;
};
...
</script>
Hopefully this gives you an idea of how we better leverage ng-repeat + DRY :)
The entire CodePen is here.

Angular template mysteriously shows only certain {{expressions}}

I'm using Angular JS v. 1.2.26 and I've spent hours trying to figure out why I cannot get certain expressions to appear in the view.
A complete, minimal, example is below (or jsfiddle here):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript">
var screen_id = '430732';
</script>
<script type="text/javascript" src="/public/scripts/vendor/angular.min.js"></script>
<script>
var tsApp = angular.module('tsApp',[]);
var screenCtrl = tsApp.controller('screenCtrl', function($scope) {
$scope.columns = [null,[null,{"name":"","id":"583","column":1,"order":1,"display_class":"static-text","block_agency":"static-text","block_mode":"static-text","custom_param":"","custom_body":"<b>This demo screen is brought to you by TransitScreen.com</b>"},{"name":"U St NW+ 17th St NW","id":"591","column":1,"order":2,"display_class":"masstransit","block_agency":"metrobus","block_mode":"bus","stops":[{"agency":"metrobus","mode":"bus","name":"U St NW+ 17th St NW","vehicles":[{"agency":"metrobus","mode":"bus","name":"U St Nw + 17th St Nw","full_route":"96","short_route":"96","destination":"Capitol Heights Station","predictions":[9,42],"direction":"Eastbound","vehicle_number":0,"logo":"","display_route":"96","longname":"96","route_class":"bus_metrobus","destination_class":"bus_metrobus","longname_accessible":null,"prediction1":9,"prediction2":42,"units":"MINUTES"},{"agency":"metrobus","mode":"bus","name":"U St Nw + 17th St Nw","full_route":"90","short_route":"90","destination":"Anacostia Station","predictions":[10,39],"direction":"Southbound","vehicle_number":1,"logo":"","display_route":"90","longname":"90","route_class":"bus_metrobus","destination_class":"bus_metrobus","longname_accessible":null,"prediction1":10,"prediction2":39,"units":"MINUTES"}],"walk_directions":"","walk_minutes":null,"arrow_svg":null}]}]];
});//end screenCtrl
screenCtrl.$inject = ['$scope'];
</script>
</head>
<body class="screen-body total-cols-1" ng-app="tsApp">
<div class="page-holder" ng-controller="screenCtrl">
<div class="col" id="col-1">
<div ng-repeat="block in columns[1]">
<div ng-include="'/public/scripts/block.html'"></div>
</div>
</div>
</div>
</body>
</html>
Here is the contents of block.html:
<div ng-switch on="block.display_class">
<div ng-switch-when="masstransit">
<table>
<div ng-repeat="stop in block.stops">
<div ng-repeat="vehicle in stop.vehicles">
<h2>Test 1</h2>
{{ stop.mode }}
{{ block.display_class }}
{{ vehicle.vehicle_number }}
<tr class="" id="">
<td class="">
<h2>Test 2</h2>
{{ stop.mode }}
{{ block.display_class }}
{{ vehicle.vehicle_number }}
</td>
</tr>
</div><!-- ng-repeat -->
</div><!-- ng-repeat -->
</table>
</div>
</div><!-- end ng-switch -->
Which outputs this...
Test 1 shows the expected values twice (because there are two items in the loop). Then in Test 2 there is only one iteration and only the middle value appears.
The problem is not identified in your code above. There is nothing wrong with ng-repeat in a TR or TD. It is more likely something is wrong in your controller or somewhere else in your code.
I created a jsfiddle which shows an example of displaying data as near the data structure in your question as I could guess. It works fine.
<table ng-controller="myCtrl" border=1>
<tr ng-repeat="stop in block.stops">
<td ng-repeat="vehicle in stop.vehicles">
<dl>
<dt>Mode:</dt><dd>{{ stop.mode }}</dd>
<dt>Class:</dt><dd>{{ block.display_class }}</dd>
<dt>Number:</dt><dd>{{ vehicle.vehicle_number }}</dd>
</dl>
</td>
</tr>
</table>
EDIT
I fixed your jsfiddle to work. See edit 2 here You can't expect Angular to work properly on malformed HTML. You cannot wrap TRs in DIVs like that. Even if Angular works who knows how some browsers might treat it. You might have data popping out after the table. Table rendering is one of the parts of HTML that is fairly strict.

Categories