ng-repeat throwing invalid Expression - javascript

I'm a total angular noob and trying to create a simple test app where. I'd like to read out some userdata in a partial. The user data is in my event controller. I assign the event controller to a form in my new.html partial after navigating to #/new via a route controller.
The error I get when trying to loop through the users in my partial is "Error: ngRepeat:iexp Invalid Expression". I can't figure out how to ng-repeat through those users.
Any thoughts?
My index.html:
<div class="container" style="width: 500px; margin: 0 auto;">
<ul class="nav nav-pills" ng-controller="NavigationController as navigationCtrl">
<li ng-class="{active: navigationCtrl.isActive(1)}">
Home
</li>
<li ng-class="{active: navigationCtrl.isActive(2)}">
Nieuw
</li>
<li ng-class="{active: navigationCtrl.isActive(3)}">
Nog een
</li>
</ul>
<div ng-view></div>
</div>
My new.html partial
<form action="" ng-controller="EventController as event">
<div ng-repeat="users as user">
<label>Name</label>
<input type="text" class="form-control" name="name" ng-model="user.name">
<br>
<label>Emailaddress</label>
<input type="email" class="form-control" name="email" ng-model="user.email">
<br>
<input class="btn btn-default" type="submit" ng-click="event.addEvent($event)" value="Klik">
</div>
</form>
And last: My angular code
(function () {
var app = angular.module('testApp', ['ngRoute']);
app.controller('NavigationController', ['$scope', '$route', function ($scope, $route) {
$scope.$route = $route;
this.activeTab = 1;
this.setActiveTab = function (tab) {
this.activeTab = tab;
};
this.isActive = function (tab) {
if ($route.current && $route.current.activeTab) {
return $route.current.activeTab === tab;
}
return false;
};
}]);
app.controller('EventController', ['$scope', '$controller', function ($scope, $controller) {
this.users = [
{name: 'aa'},
{name: 'bb'}
];
this.addEvent = function (e) {
e.preventDefault();
console.log(this);
};
}]);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/new', {
templateUrl: 'partials/new.html',
controller: 'NavigationController',
activeTab: 2
}).
when('/another', {
templateUrl: 'partials/another.html',
controller: 'NavigationController',
activeTab: 3
}).
otherwise({
redirectTo: '/',
controller: 'NavigationController',
activeTab: 1
});
}]);
})();
I've tried changing this for $scope to no avail.

You write ng-repeat in wrong way in your new.html partial page
it should be like
new.html
<div ng-repeat="user in users">

Correct syntax for ng-repeat is
<element ng-repeat="item in [1,2,3]">
Also you can use things like track by $index if you have duplicated values in your collection like [1,1,1].
Ref. https://docs.angularjs.org/api/ng/directive/ngRepeat

There are few issues in your code. Please change all this references to $scope and then quickly fix below html code:
<div ng-repeat="user in users">
It should work but update me otherwise also.
Working demo for your reference (route codes excluded for demo purpose only)
thanks,
Ashok

you have not written ng-repeat in right way change it to:
<div ng-repeat="user in users">

Related

Angular Js push to array from dynamic ng-repeat directive to a controller

I need a big favor. I have this ng-repeat directive
appTitan.directive('questionsAnswers', function() {
return {
restrict: 'E',
templateUrl: '/js/directives/questionsAnswers.html',
replace: true,
scope: {
questions: '=',
chosenAnswersArr: '='
},
link: function(scope) {
scope.chosenAnswers = function(selection) {
scope.chosenAnswersArr.push(selection);
};
}
};
});
And this is used accordingly in the template
<div class="question-answers__item__wrapper">
<div class="question-answers__item__question">
<h3>{{ questions.questionName }}</h3>
</div>
<div class="question-answers__item__answers">
<ul class="row">
<li class="col-sm-6" data-answer-item-id="{{questions.answerOne.isCorrect}}" ng-click="chosenAnswers(questions.answerOne.isCorrect)">
<p>{{questions.answerOne.value}}</p>
</li>
<li class="col-sm-6" data-answer-item-id="{{questions.answerTwo.isCorrect}}" ng-click="chosenAnswers(questions.answerTwo.isCorrect)">
<p>{{questions.answerTwo.value}}</p>
</li>
<li class="col-sm-6" data-answer-item-id="{{questions.answerThree.isCorrect}}" ng-click="chosenAnswers(questions.answerThree.isCorrect)">
<p>{{questions.answerThree.value}}</p>
</li>
<li class="col-sm-6" data-answer-item-id="{{questions.answerFour.isCorrect}}" ng-click="chosenAnswers(questions.answerFour.isCorrect)">
<p>{{questions.answerFour.value}}</p>
</li>
</ul>
</div>
</div>
and added in HTML like this
<li class="question-answers__item" ng-repeat="questions in quizData.questionAndAnswers" elem-height>
<questions-answers questions="questions" chosenAnswersArr="chosenAnswersArr"></questions-answers>
</li>
I have this chosenAnswer ng-click function in my template.
Here's my controller
appTitan.controller('MainController', ['$scope', '$http', '$location', function($scope, $http, $location) {
'use strict';
//Generate scores
$scope.chosenAnswersArr = [];
}]);
I am unable to push data from directive to the controller. What is that I have to do to make it work.
The error I'm getting is
angular-1.4.8.min.js:107 TypeError: Cannot read property 'push' of undefined
I did try adding the controller property(MainController) to the directive but it was breaking the data. Please note that the data is pulled using the same controller using $http.get(I didn't add that line here). I am mentioning this because to let you know that the data is dynamic.
How can I push a data from my directive to the controller?

How to make href in button inside collapse

I have a collapsed model which show more information about client, and insid it, I have a button, when I click, I don't get the informations of the specific client, I get data of all clients
<ion-list ng-repeat="x in names">
<a class="item item-icon-left " >
<i class="icon ion-android-arrow-dropdown-circle" ng-model="collapsed" ng-click="collapsed=!collapsed"></i>
{{x.Marque}}
</a>
<div ng-show="collapsed">
<table>
<thead >
<td>
<label> Code: </label> {{x.CodeClient}} <br/>
<label> Nom: </label> {{x.NomClient}} <br/>
<a class="button button-info" ui-sref="modifClient({CodeClient: x})" >
Enregistrer
</a>
...
app.js
$stateProvider.state('modifClient', {
url: '/modifClient',
templateUrl: 'templates/modifClient.html',
params: {CodeClient: null},
controller: 'ConsultClientCtrl'
});
app.controller("ConsultClientCtrl", function($scope, $http) {
$scope.loadClient = function(){
$http.get("http://localhost/deb/debut.php")
.success(function(data){
$scope.names = data;
});
}
});
modifClient.html
<ion-content class="padding" ng-controller="ConsultClientCtrl" ng-repeat="x in names | filter: {CodeClient: thisX}" >
<ion-list ng-repeat="x in names | filter: {CodeClient: thisX}: true">
<div class="item item-divider center-text" ng-model="CodeClient"> {{x.CodeClient}} </div>
......
You have to use the framework's href: ngHref or ng-click
<a class="button button-info" ng-href="/modifClient"> ...
LE: I've created a pen for this case. The problem is that you have an <a> in <a> and when you click it then it get's confused.
So I've changed the <a ng-show="collapsed"> to <div ng-show="collapsed"> and now works as expected (see pen too).
If you are using Angular ui-router and modifClient is a state in your router, you better use the Angular ui-sref attribute instead of HTML href.
Your code would be :
<a class="button button-info" ui-sref="modifClient">
Edit:
If you want to pass an object param in the ui-sref you can do it like this:
<a class="button button-info" ui-sref="modifClient({CodeClient: x.CodeClient})">
And change your state settings to include a params object:
$stateProvider.state('modifClient', {
url: '/modifClient',
templateUrl: 'templates/modifClient.html',
params: {CodeClient: null},
controller: 'ConsultClientCtrl'
});
Note:
Note that you should also update your ConsultClientCtrl controller with a $scope.CodeClient variable so it can be updated from the ui-sref.
You can read How to pass parameters using ui-sref in ui-router to controller for further options.
Edit 2:
After reading your last Edit, I can see that you don't have a CodeClient variable in your controller, so update it like this:
app.controller("ConsultClientCtrl", function($scope, $http) {
$scope.CodeClient = null;
$scope.loadClient = function(){
$http.get("http://localhost/deb/debut.php")
.success(function(data){
$scope.names = data;
});
}
});
And in your HTML just use:
<div class="item item-divider center-text"> {{CodeClient}} </div>
Without <ion-list ng-repeat ...> and the filter part as we already got the CodeClient variable in the Controller.
Thanks for every one,This is the solution I found:
change the code of the button:
<a class="button button-info" ng-href="#/modifClient/{{x.CodeClient}}" >
Enregistrer </a>
And in app.js, I had to use $state:
app.controller("ConsultClientCtrl", function($scope, $http,$state) {
$scope.loadClient = function(){
$http.get("http://localhost/deb/selectClient.php")
.success(function(data){
$scope.thisX = $state.params.CodeClient;
$scope.names = data;
});
}
});
And changing the state provider to this:
$stateProvider.state('modifClient', {
url: '/modifClient/:CodeClient',
templateUrl: 'templates/modifClient.html',
controller: 'ConsultClientCtrl'
});

sharing data between templates in angular, how to?

I have 2 template, in 1st template I use the function and after its successful implementation,i want to get data in a 2nd template. How can I do it? Both template using the same controller
My 1st template:
<form ng-submot='vm.search(q)' class="header-search">
<input class="header-search-input" ng-model='q' placeholder="Search">
<button type="button" class="btn btn-default ic-search" aria-label="Left Align" ng-click='vm.search(q)'>
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
</form>
My 2nd template:
<h3>Результат поиска по запросу: {{q}}</h3>
<ul ng-repeat='item in items'>
<li>{{item.name}}</li>
</ul>
controller:
(function() {
'use strict';
angular
.module('beo.layout.controllers')
.controller('NavbarController', NavbarController);
NavbarController.$inject = ['$scope', '$http', '$location'];
function NavbarController($scope, $http, $location) {
var vm = this;
vm.logout = logout;
vm.search = search;
function search(q) {
$http.post('/api/v1/search/', {
q: q
}).success(function(data) {
$location.path('/search/')
$scope.q = q;
$scope.items = data;
})
}
})();
I would suggest you use cache for best practice. While you are using two templates and when you load your another template it's also going to reload your controller. If you are done with your search in first template then you can save result in cache and then when you redirect to template then just look into that if there is any result then just show it.
Setting $scope equal to the value of the input field should allow you to pass the data from the 1st template to the 2nd template.
Use ng-if to switch between two piece of HTMl snippets. By the way, template is a special term in Angular, indicating something like template in a directive.
For example:
<div ng-if="!items">
<form ng-submot='vm.search(q)' class="header-search">
<input class="header-search-input" ng-model='q' placeholder="Search">
<button type="button" class="btn btn-default ic-search" aria-label="Left Align" ng-click='vm.search(q)'>
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
</form>
</div>
<div ng-if="items">
<h3>Результат поиска по запросу: {{q}}</h3>
<ul ng-repeat='item in items'>
<li>{{item.name}}</li>
</ul>
</div>
After you have retrived the data successfully, i.e., the variable items is true, Angular will switch to the 2nd template for you.
NOTE: you are using vm (this) and $scope on the controller at them same time, which is not encouraged.
To do it "The angular way" you should use directives. Within directives you can require controllers of other directives so you can share data as you need. An example is here: How to require a controller in an angularjs directive
You can get data after a user clicks on the search button, in your code i.e. through vm.search function in the controller which should be used to get data through an api call check this below example.
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
function DefaultController() {
var vm = this;
vm.items = [];
vm.search = search;
function search(searchTerm) {
// perform ajax call and set data here on vm.items property
vm.items = data;
}
}
var data = [
{ name: 'Audi' },
{ name: 'Lamborghini' },
{ name: 'Jaguar' }
];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<form name="searchForm" novalidate="novalidate" ng-submit="searchForm.$valid && ctrl.search(ctrl.searchTerm)">
<label for="searchBox">Search</label>
<input type="text" name="searchBox" ng-model="ctrl.searchTerm" ng-required="true">
<button ng-click="isSubmitted = true">Submit</button>
<span style="color: red;" ng-show="isSubmitted && searchForm.searchBox.$invalid">Search term is required</span>
</form>
<label ng-show="ctrl.items.length">Items matching your search</label>
<div ng-repeat="item in ctrl.items">
{{item.name}}
</div>
</div>
</div>

how to pass data from controller to directive using $emit

I had strucked in passing value from controller to directive
I have two arrays in my controller
$scope.displayPeople.push(data.userName);
$scope.displayOrg.push(data.orgname);
i need to pass these data from controller to directive
my directive
<div>
<div class="multitext-wrap blue-border">
<ul inputfocus>
<!--<li class="tag" ng-repeat="list in selecteditemsdisplay track by $index" ng-class="{selected: $index==selectedIndex}" >-->
<!--<span class="tag-label">{{list}}</span><span class="tag-cross pointer" ng-click="Delete($index,selecteditemslist[$index],list,searchid)">x</span>-->
<!--</li>-->
<li class="tag" ng-repeat="list in displayItems track by $index" ng-class="{selected: $index==selectedIndex}" >
<span class="tag-label">{{list}}</span><span class="tag-cross pointer" ng-click="Delete($index,selecteditemslist[$index],list,searchid)">x</span>
</li>
<li class="">
<input type="text" ng-model="searchModel" ng-keydown="selected=false" ng-keyup="searchItem(searchModel,searchobj)"/>
</li>
</ul>
</div>
<div class="typeahead" ng-hide="!searchModel.length || selected">
<div class="typeahead" ng-repeat="item in searchData | filter:searchModel | limitTo:8" ng-click="handleSelection(item,searchobj,$index,searchid)" style="cursor:pointer" ng-class="{active:isCurrent($index)}" ng-mouseenter="setCurrent($index)">
<div class="bs-example">
<div class="list-group list-group-item active">
{{item.displayConfig[0].propertyValue}} {{item.displayConfig[1].propertyValue}}
</div>
</div>
</div>
</div>
</div>
I was using $emit to send
in controller
$rootScope.$emit("displayEvent", {displayItems: $scope.displayPeople});
$rootScope.$emit("displayEvent", {displayItems: $scope.displayOrg});
in directive
$rootScope.$on('displayEvent', function (event, args) {
$scope.displayOrgs = args.displayItems;
console.clear();
console.info($scope.displayOrgs);
});
by doing this i getting duplicates in place of org (both people and org wher coming )
how can i solve this problem please hepl me thanks in advance
By declaring 'scope: false' you´re able to access the controller´s scope in your directive. 'false' means 'do not create an isolated scope, inherit the controllers'.
.directive('myDirective', function() {
return {
scope: false,
link: function($scope){
//Do stuff with $scope.displayOrgs
//Do stuff with $scope.displayPeople
}
};
});
This option will create an isolated scope and inherits the selected variables. This is a cleaner way of doing it.
.directive('myDirective', function() {
return {
scope:{
displayPeople:'=',
displayOrg :'=',
},
link: function($scope){
//Do stuff with $scope.displayOrgs
//Do stuff with $scope.displayPeople
}
};
});
using $emit for communication between controller and directive is not a preferable.
you need to use "=" scope of directive to allow two-way communication between controller and directive like:
directive
angular.module('YourModuleName').directive('yourDirectiveName',function () {
return{
restrict:'E',
scope:{
displayPeople:'=',
displayOrg :'=',
},
link: function postLink(scope, element, attrs) {
}
}
});
template respective to controller
<yourDirectiveName displayPeople="displayPeople" displayOrg ="displayOrg "></yourDirectiveName >

Controller Function is not getting called on ng-click

This is my View Code
<div ng-controller="signupCtrl">
<ul class="list-group" >
<li class="list-group-item">
<div class="form-group">
<input type="text" ng-model="signupCtrl.firstName">
</div>
...
</div>
<div class="form-group">
<div class="pull-right">
<button ng-click="signupCtrl.signupUser()">Register</button>
</div>
</div>
</li>
</ul>
</div>
Update- This is my Controller Code ##
someAppControllers.controller('signupCtrl', [
'$window',
'$scope',
'HttpReqHandlerService',
'$location',
'localStorageService'],
function($window, $scope, HttpReqHandlerService,
$location, localStorageService) {
$scope.signupUser=function signupUser() {
alert("hello");
}]);
The button is not calling signupUser function in my controller
Use $scope.signupUser instead of this.signupUser
Change you code as
someAppControllers.controller('signupCtrl', ['$window', '$scope',
function ($window, $scope) { // Here you have to define function an pass window and scope
$scope.signupUser = function signupUser() {
alert("hello");
};
}
]);
Additionally, You have syntax error.
HTML
Instead of
<input type="text" ng-model="signupCtrl.firstName">
<button ng-click="signupCtrl.signupUser()">Register</button>
Use
<input type="text" ng-model="firstName">
<button ng-click="signupUser()">Register</button>
You've written your markup as though you used the controller as syntax. To make it work just change your ng-controller="signupCtrl" to ng-controller="signupCtrl as signupCtrl";

Categories

Resources