onclick="AuthorityCheck({{meeting.people}})", expected identifier, string or number - javascript

I am having trouble with sending {{meeting.people}} value to JS function. Code is following
Error message says: Expected identifier, string or number. {{meeting.people}} is plain text.
Link:
<li class=" seriesblock ms-ContentAccent1-bgColor" ng-repeat="meeting in meetings | SeriesTitleFilter:filterString" >
<a id="meetingItem_{{meeting.id}}" onclick="AuthorityCheck({{meeting.people}})" href="Meeting.aspx?seriesId={{meeting.id}}"></a>
</li>
JS function:
function AuthorityCheck(people){
var ppl = people;
}
Note, that meetingItem_{{meeting.id}} works correctly.
Any ideas, how could I fix this problem?

Angular doesn't like mixing html event handlers with templates. You will need to use ng-click which calls a $scope method aliasing AuthorityCheck,. similar to this answer:
function AuthorityCheck(p) {
alert(p);
event.returnValue = false;
}
var meetingApp = angular.module('meetingApp', []);
meetingApp.controller('meetingCtrl', function ($scope) {
$scope.meetings = [
{ 'id': 1, people: 'fred' },
{ 'id': 2, people: 'bob' }
];
// set the alias as a scope method
$scope.meetingClick = AuthorityCheck;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app="meetingApp">
<div ng-controller="meetingCtrl">
<ul>
<li class="seriesblock ms-ContentAccent1-bgColor" ng-repeat="meeting in meetings">
<a id="meetingItem_{{meeting.id}}" ng-click="meetingClick(meeting.people)" href="Meeting.aspx?seriesId={{meeting.id}}">{{meeting.people}}</a>
</li>
</ul>
</div>
</div>

Related

How do I display this json file correctly in ng-repeat?

I'm trying to create a Store page for my website. I want to display the following json file in ng-repeat:
{
"cupcakes": {
"Vanilla": [
{"price":"9.99", "stock":"20", "amount":"8",
"ingredients":"flour, sugar, vanilla extract",
"popular":true}
],
"Maple": [
{"price":"9.99", "stock":"15", "amount":"8",
"ingredients":"flour, sugar, maple syrup",
"popular":true}
]
},
"cookies": {
"Vanilla": [
{"price":"7.99", "stock":"50", "amount":"12", "ingredients":"flour, sugar, vanilla extract"}
],
"Maple": [
{"price":"7.99", "stock":"50", "amount":"12", "ingredients":"flour, sugar, maple syrup"}
]
}
}
I want to display the type item (cupcake or cookie) then the type of each item (vanilla or maple) then the unique attributes and be able to filter and search through them. I'm thinking I may have to restructure my json file, but I'm not sure. Should I sort out the items ahead of time in my controller with a forEach? Here is my controller:
angular.module('root', [])
.controller("index", ['$scope', '$http', function ($scope, $http) {
$scope.name = null;
$scope.email = null;
$scope.comments = null;
$scope.reason = null;
$scope.employees = [];
$scope.items = [];
$http.get('http://localhost:8000/employees.json').then(function(result) {
$scope.employees = result.data.records;
});
$http.get('http://localhost:8000/inventory.json').then(function(result) {
$scope.items = result.data;
});
$scope.isEnabled = function() {
if ($scope.name && $scope.email && $scope.comments) {
return false;
}
else {
return true;
}
}
}])
In Javascript, almost everything is an array. You can iterate over an array of objects or, in an object you are iterating over his properties.
The following script should do the work.
<div ng-repeat="(itemLabel, itemValue)in items">
{{itemLabel}}
<div ng-repeat="(flavorLabel, flavorValue)in itemValue">
{{flavorLabel}}
<div ng-repeat="object in flavorValue">
<div ng-repeat="property in object">
{{property}}
</div>
</div>
</div>
</div>
jsfiddle
Here is a way for showing your data using ng-repeat:
<div ng-repeat="(foodKey, foodVal) in foods">
<b>{{foodKey}}</b>
<div ng-repeat="(typesKey, typesVal) in foodVal">
<span>{{typesKey}}</span>
<ul ng-repeat="types in typesVal">
<li ng-repeat="(key, val) in types">
{{key}} : {{val}}
</li>
</ul>
</div>
</div>
Of course it will only work if foods is the json you posted in your answer.
Here is a working jsFiddle.
For more information on ng-repeat see here.
Just going through your JSON.
<div ng-repeat="(key, value) in inventory">{{key}}
<ul>
<li ng-repeat="(material_key, material_value) in value">{{material_key}}
<ul>
<li ng-repeat="(options_key, options_value) in material_value[0]">{{options_key}} - {{options_value}}</li>
</ul>
</li>
</ul>
<br>
Have a look at this plunker. I hope this will solve you problem.
you need multiple ng-repeaters hope this plunker is your requirement
you can do anything with the keys of your JSON in javascript , by converting the JSON to object by
JSON.parse(json);
later on you can access any key and that will be an object/hashmap to loop or sort
So in your case, your API result can be parsed like
var resultData = JSON.parse(result.data);
Later you can do ng-repeat in your view some thing like
[{id: 'foo'}, {id: 'bar'}] | orderBy:'id'

AngularJS Filter expression not being updated

I have am dealing with two HTML files and one controller. In one HTML file I have a search bar:
<a ui-sref="allSubmissions">
<input id="searchBar" ng-controller="submissions" ng-model="searchString" class="searchBar" type="text" placeholder="Search">
</a>
Along with some other stuff. In a separte HTML file, I have a list of submissions that I populate with ng-repeat:
<div class="container" ng-controller="submissions">
<ul class="subsList">
<ul>
<li ng-repeat="item in submissionCollectionTest | filter: searchString" class="submissionDivider hover">
<span class="ageText">{{item.age}}</span>
<span class="submissionsText">{{item.submission}}</span>
<span class="descriptionText">{{item.description}}</span>
</li>
</ul>
</ul>
</div>
Along with some other code. It makes sense in my complete app that these files be separate, however, I cannot get the search input to tie to the filter expression and automatically update.
In my controller, i have the following scope variable:
myApp.controller('submissions',function($scope){
$scope.searchString = '';
When I click in the search bar, it takes me to the new page with shows all the content populated from the ng-repeat, then I want to filter the content by typing in the search bar. This does work when I have the search bar code in the same place as the content. How can I update "searchString" globally so that the filter responds when it changes? Thanks
You could use a broadcast from one controller and listen in another. If you're using multiple routes, then you'll want to store the search term in a service.
Example: https://jsfiddle.net/h0bd88dc/
function SearchSubmissionsCtrl($rootScope,Service) {
var vm = this;
vm.searchString = Service.searchString;
vm.search = search;
function search() {
Service.searchString = vm.searchString;
$rootScope.$broadcast('search', vm.searchString);
}
}
function SubmissionsCtrl($scope,Service) {
var vm = this;
vm.searchString = Service.searchString;
vm.items = [{
age: 22,
submission: 'Yes',
description: 'Yo'
}, {
age: 5,
submission: 'Derp',
description: 'Hey'
}];
$scope.$on('search', function(e, string) {
vm.searchString = string;
})
}
function Service() {
var service = {
searchString: null
};
return service;
}

Setting a scope variable from a directive with AngularJS

I've gone through what must be 20 similar questions asked on SO but have yet to find a solution for my situation, so I hope you guys can help me out.
The goal is to sort the list of names by the property that's provided in the "sort-type" attribute of the directive, but only for the list within each controller (not all lists at the same time).
HTML
<div ng-controller="TestController as testOne">
<b>By:</b> {{testOne.sortType}}<br>
<b>Reverse:</b> {{testOne.sortReverse}}<br>
<div ng-repeat="item in testOne.list">
<p table-sort sort-type="name" sort-reverse="false">Sort by name</p>
<ul>
<li ng-repeat="childItem in testOne.childList | orderBy:testOne.sortType">{{childItem.name}}</li>
</ul>
</div>
</div>
<br><br>
<div ng-controller="TestController as testTwo">
<b>By:</b> {{testTwo.sortType}}<br>
<b>Reverse:</b> {{testTwo.sortReverse}}<br>
<div ng-repeat="item in testTwo.list">
<p table-sort sort-type="name" sort-reverse="false">Sort by name</p>
<ul>
<li ng-repeat="childItem in testTwo.childList | orderBy:testTwo.sortType">{{childItem.name}}</li>
</ul>
</div>
</div>
Javascript (Angular)
var app = angular.module('demo', []);
app.controller('TestController', TestController);
function TestController() {
var vm = this;
vm.sortType = 'oldOrder';
vm.sortReverse = false;
vm.list = [1];
vm.childList = [{ name: 'Jimmy' },
{ name: 'Danny' },
{ name: 'Bobby' }];
}
/////////////////////////////////////
app.directive('tableSort', tableSort);
function tableSort() {
var directive = {
restrict: 'A',
link: linkFunc,
};
return directive;
function linkFunc(scope, element, attr) {
element.on('click', function() {
if(scope.sortType === attr.sortType) {
scope.sortReverse = !scope.sortReverse;
} else {
scope.sortType = attr.sortType;
}
});
}
}
JSFiddle here
My actual application is a bit more complex but I've tried to abstract it as much as possible.
Thanks for looking :)
Ok Several things going on here:
you are using the controllerAs syntax on your templates but
you are changing scope variables in your directive. hence your
controller variables are never changed.
your directive is inside of the ng-repeat which means that
you are actuating actually on a child scope so if you are setting
variables directive on the scope your ng-repeat won't be able to
reach them because they are being set after the child scope are
created.
you are using element.on which executes outside of angular
digest which means you would have to call scope.$apply to let
angular know that something happened.
Take a look at this
https://jsfiddle.net/rez8ey12/
i hope it helps

Remove object from ng-repeat

I have a PhoneGap + Onsen UI + AngularJS app in the works, where I have a list in the view, where the items will be fetched from the controllers variable.
I want to be able to remove items from this list, by clicking on them.
The list looks like this:
<ons-list>
<ons-list-item modifier="tappable" class="item" ng-repeat="citem in completeditems" ng-click="delete(citem)">
<ons-row>
<ons-col>
<div class="titlediv">
<header>
<span class="item-title">{{citem.name}}</span>
</header>
</div>
<div class="item-dates">
<span class="item-start">{{citem.start}}</span>
</div>
</ons-col>
</ons-row>
</ons-list-item>
</ons-list>
The completeditems object in the $scope looks like this:
var completeditemname = "item" + i;
$scope.completeditems[completeditemname] = {
id : "ID",
name : "Name for it",
start: "Start date"
}
Tried the following method, but it didn't work out:
$scope.delete = function(item) {
var index = $scope.completeditems.indexOf(item);
$scope.completeditems.splice(index,1);
//$scope.completeditems.remove(item); //tried this aswell
$scope.$apply() //i need this to update the view
}
You do not need the $scope.$apply() invocation. As you are making alterations to scope variables the digest cycle will be triggered anyhow and you will be encountering an error because of this I believe.
UPDATED:: You're working with an actual object by the looks of it so I've updated the code in the plunker to help you out. It means altering the ng-repeat to use both key and value.
Here is a simple plunkr showing a basic example of what you are trying to do with a one liner in the delete function http://plnkr.co/edit/NtQD....
<body ng-app="myApp">
<div ng-controller="myController as ctrl">
<ul ng-repeat="(key, value) in ctrl.items track by key">
<li ng-click="ctrl.delete(key)">{{value}}</li>
</ul>
</div>
</body>
var myApp = angular.module('myApp', [])
.controller('myController', [
'$scope',
function($scope) {
var self = this;
self.items = {
item1: {
id: 1,
name: 'a'
},
item2: {
id: 2,
name: 'b'
},
item3: {
id: 3,
name: 'c'
}
};
self.delete = function(key) {
delete self.items[key];
};
}
]);
Hope that helps you out!
$scope.$apply() should only be used when changes are coming in from outside the Angular framework. Since your delete() function is being called from an ng-click, it is already being managed by Angular and calling $apply() will raise a "$digest is already in progress" error (check your browser console). Removing that call will most likely get your code working.

Understanding scope, ng-click and the angular-way

While working on the phone tutorial i wondered how to implement this use case
user clicks on add phone
the function addItem is fired and the phone.id is passed
the relevant phone is retrieved and the quantity increased by 1
the increased quantity should be displayed in the input
You can find my codepen demo here and this is the relevant code
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
<b>{{phone.name}} </b>
<i ng-click="addItem(phone.id)"> add phone</i>
<input name='{{phone.id}}'
value='{{phone.qty}}'
ng-readonly='{{phone.orderReadonly}}' /><br />
<p>{{phone.snippet}} </p>
</li>
</ul>
and the javascript
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function($scope) {
$scope.phones = [
{'id': 1, 'name': 'Mui 1'
,'snippet': 'Our newcomer from asia.'
,'orderReadonly' : 'false', 'qty': 4}
....
,{'id': 4, 'name': 'Msft Lumiaâ„¢'
,'snippet': 'Who knows what windows 10 will bring'
,'orderReadonly' : 'true','qty': 2}
];
$scope.orderProp = 'id';
$scope.addItem = function(phone_id) {
// from http://stackoverflow.com/questions/15610501/
var found = $filter('filter')($scope.phones, {id: phone_id}, true);
if (found.length) {
found[0].qty = found[0].qty + 1;
} else {
$scope.selected = 'Not found';
}
}
});
Current status
passing the id works
finding the phone does not work: var found = $filter('filter')($scope.phones, {id: phone_id}, true); // found in http://stackoverflow.com/questions/15610501/
increasing quantity does not work
My questions are
if and how onclick / ng-click should be used in the angular way
how to solve my requirement - increase phone quantity onclick on <i>add phone</i>
I don't know why qty doesn't work - it should, unless your filter doesn't find a match.
But you shouldn't even be doing this. Instead of passing the id of the object and then locating the object to change its property, just pass the object phone itself:
<i ng-click="addItem(phone)"> add phone</i>
Then, in the controller, simply do this:
$scope.addItem = function(phone) {
phone.qty = phone.qty + 1;
}
Summarising the two above answers. The "++" increment will not work on the variable or object property from the "ng-click" directive, so instead you should use:
variable = variable + 1
And in connection to the original question the
<i ng-click="phone.qty = phone.qty + 1"> add phone</i>
will do the trick.
To answer your first question:
Using ng-click runs an angular expression inside Angular's scope. If you use the onclick simply runs javascript code.
So if you have some variable 'numPhones' initialized inside your controller, then you can have:
ng-click="numPhones = numPhones + 1"
and the numPhones variable will be incremented.
On the other hand:
onclick="numPhones = numPhones + 1"
doesn't reference the surrounding angular scope.
So if you're using Angular, you probably wouldn't want onclick at all.
Here's an example:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
angular.module('phones', [])
</script>
</head>
<body ng-app='phones'>
<div>
{{ numPhones }}
<button ng-click="numPhones = numPhones + 1"> add 1</button>
</div>
</body>
</html>

Categories

Resources