Ng-Click events not firing - angularjs

Hi I just started learning Angular today and I have some problems when trying to bind an event.Here is what I have done so far.I loaded all my scripts on my html page:
<script src="Scripts/jquery-1.9.0.js"></script>
<script src="Scripts/angular.js"></script>
<script src="app/modules.js"></script>
<script src="app/Controllers/studentGradesController.js"></script>
I then create a file modules and defined my module:
var angularTestApp = angular.module('AngularTestApp', []);
I then created a controler:
angularTestApp.controller('StudentGradesController', function StudentGradesController($scope) {
$scope.students = [
{
firstName: 'Lorem',
lastName: 'Ipsum',
age: 24,
grade: 5,
votes: 0
},
{
firstName: 'Lorem',
lastName: 'Ipsum',
age: 250,
grade: 21,
votes: 0
}
...
];
$scope.downVote = function(student) {
student--;
};
$scope.upVote = function (student) {
alert("I work");
};
});
I then binded the controller on my html:
<article class="container" ng-controller="StudentGradesController">
<section>
<section ng-repeat="student in students" class="row">
<div class="col-md-1 text-center">
<i class="fa fa-chevron-up pointer" ng-click="upVote"></i>
<span ng-bind="student.votes" class="center-block"></span>
<i class="fa fa-chevron-down pointer" ng-click="downVote"></i>
</div>
<div class="well col-md-11">
<div>
<span ng-bind="student.firstName"></span>
<span ng-bind="student.lastName"></span>
</div>
</div>
</section>
</section>
</article>
When I try to click on the binded items nothing happens.No errors are thrown.Can anyone tell me what I am doing wrong?

Call a function using ng-click instead of just referencing it. Adding the parenthesis will make it a function call:
<i class="fa fa-chevron-up pointer" ng-click="upVote(student)"></i>
That said; the i tag is just puts text in italics and you have no text specified, so there is nothing to click on.

The argument you provide in ng-click is not a function, it's an AngularJS expression. It's like a Javascript expression. You should use ng-click="upVote(student)" to call it.

try ng-click="downVote(student)" and ng-click="upVote(student)"

Related

ng-model saving with a recursive display

Setup
I have a frontend that displays a JSON. One can edit the values in the JSON via an ng-model textarea with a save button.
It does this by recursively calling an object like this:
In tree-object-edit.html:
...
<h4 class="capitalize">{{ item_key }}: </h4>
<textarea rows="2" cols="60" ng-model="item"></textarea>
<div ng-if="item.properties">
<ul>
<li ng-repeat="(item_key, item) in item.properties" ng-include="'html/tree-object.html'"></li>
</ul>
</div>
This is called by this my-definition.html
<form name="form"
role="form"
novalidate
class="ng-scope ng-invalid ng-invalid-required ng-dirty ng-valid-minlength"
ng-controller="MyDefinitionDetailController">
<h4>My Definition Edit: {{myDefinition.name}}</h4>
<ul ng-repeat="(item_key,item) in myDefinition" ng-include="'html/tree-object-edit.html'"></ul>
<button type="submit" ng-click="create()">
<span>Save</span>
</button>
</form>
My my-defintion-detail.controller.js contains
$scope.create = function () {
MyDefinition.save($scope.myDefinition,
function () {
});
};
Problem
Clicking save does not save the myDefintion because myDefiniton has not been changed. Only item has been changed.
Question
Is there a way to make the myDefiniton change when the item "within it" changes?
UPDATE 1
I have found that:
<textarea rows="2" cols="60" ng-model="myDefinition[item_key]"></textarea>
Does work for the first level of the recursion
You correctly noted, that ng-model="myDefinition[item_key]"(parent[key] at my example) works, - changes will reflect into desired model, if you will make them on property level not on direct value. So, besides passing value and key to nested template, you also should pass parent object, that way chain of references from actual value to "head" will be created:
angular.module('app', []).controller('ctrl', ['$scope', function($scope) {
$scope.value = {
identity: {
name: 'Max',
surName:'Smith',
},
birthDay: {
year: 1990,
month: 2,
day: {
weekDay: 'friday',
number: '13'
}
},
firstLevel: 'abc'
}
$scope.isObject = function(value){
return angular.isObject(value);
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller="ctrl">
<script type="text/ng-template" id="template">
{{key}}
<ul ng-init='temp=value'>
<input ng-if='!isObject(value)' type='text' ng-model='parent[key]'/>
<li ng-if='isObject(temp)' ng-repeat='(key, value) in temp' ng-init='parent=temp' ng-include="'template'"></li>
</ul>
</script>
<ul ng-init='parent=value'>
<li ng-repeat='(key, value) in value' ng-include="'template'"></li>
</ul>
{{value | json}}
</div>
Just to add a perhaps more elegant solution: (Note if you update angular recursive directives also becomes a thing)
angular.module('app', ['dotjem.angular.tree']).controller('ctrl', ['$scope', function($scope) {
$scope.value = {
identity: {
name: 'Max',
surName:'Smith',
},
birthDay: {
year: 1990,
month: 2,
day: {
weekDay: 'friday',
number: '13'
}
},
firstLevel: 'abc'
}
$scope.isObject = function(value){
return angular.isObject(value);
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgithub.com/dotJEM/angular-tree-bower/master/dotjem-angular-tree.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul dx-start-with="value as parent">
<li ng-repeat="(key, value) in parent">
{{key}}
<input ng-if="!isObject(value)" type="text" ng-model="parent[key]"/>
<ul ng-if="isObject(value)" dx-connect="value"></ul>
</li>
</ul>
<pre>{{value | json}}
</pre>
</div>

ng-click on img not working inside ng-repeat

In my view I have a list of icons that when clicked, should call a function from the controller.
View
<div ng-controller="EditorController" class="main-div">
<aside>
<div ng-repeat="icon in EditorIcons">
<img ng-click="changeme()"
data-ng-src="{{icon.source}}"
alt="{{icon.name}}"/>
</div>
</aside>
</div>
Controller
app.controller('EditorController', function($scope) {
$scope.EditorIcons = [ ... ];
$scope.changeme = function() {
console.log("changing");
}
}
I've seen this question asked before, yet I still wasn't able to find out the problem here. What am I doing wrong?
UPDATE
I've found the problem. I had a z-index of -1 on the aside element
Assuming that EditorIcons is a collection in your controller, and changeme is a method inside of your controller, the you need t remove the $parent:
<div ng-repeat="icon in EditorIcons">
<img ng-click="changeme()"
ng-src="{{icon.source}}" alt="{{icon.name}}" />
</div>
Secondry you werte missing quotes " in your alt definition
Ok I just tried to make a fiddle and it works fine:
https://jsfiddle.net/pegla/8807dvrr/2/
<div ng-app>
<div ng-controller="SomeCtrl">
<aside>
<div ng-repeat="icon in EditorIcons">
<img ng-click="changeme()" data-ng-src="{{icon.source}}" alt="{{icon.name}}" />
</div>
</aside>
</div>
</div>
function SomeCtrl($scope) {
$scope.EditorIcons = [{
source: '',
name: 'icon-1'
}, {
source: '',
name: 'icon-2'
}];
$scope.changeme = function() {
console.log("changing");
}
};
So your problem has to be somewhere in declaration of controller or ng-app since code works, also check that data you have in editor icons is good.

Angular Js: Get data from span and append in another span

Hello everyone I am trying to learn Angular and I want to get data from a Span and append in another span. Please help me out fro there.
My code is here
<div ng-app="" >
<div>
Name: <span ng-init="firstName='Ritu'">Ritu</span>
Address: <span ng-init="address='Uttam Nagar'">Uttam Nagar</span>
City: <span ng-init="city='West Delhi'">West Delhi</span>
State: <span ng-init="state='Delhi'">Delhi</span>
pin: <span ng-init="pin='110045'">110045</span>
<button>Click and Show</button>
</div
And I want to show like that but after click on show button
<p>Name <span ng-bind="firstName"></span></p>
<p>Address <span ng-bind="address"></span></p>
<p>City <span ng-bind="city"></span></p>
<p>State <span ng-bind="state"></span></p>
<p>pin <span ng-bind="pin"></span></p>
</div>
Thanks in advance.
I created a plnkr that does what you would like to do . Check it out http://plnkr.co/edit/8xZik28CECenuPpLgdpq?p=preview
I used ng-show directive which results as css display (block or none) and you may use ng-if if you desire but ng-if has performance impact when used so many times , and you can find alternate ways of this I just wanted to give a quick move .
the html part
<body ng-controller="MainCtrl">
Name: <span ng-init="firstName='Ritu'">Ritu</span>
Address: <span ng-init="address='Uttam Nagar'">Uttam Nagar</span>
City: <span ng-init="city='West Delhi'">West Delhi</span>
State: <span ng-init="state='Delhi'">Delhi</span>
pin: <span ng-init="pin='110045'">110045</span>
<button data-ng-click="show=!show">Click and Show</button>
<div ng-show="show">
<p>Name <span ng-bind="firstName"></span></p>
<p>Address <span ng-bind="address"></span></p>
<p>City <span ng-bind="city"></span></p>
<p>State <span ng-bind="state"></span></p>
<p>pin <span ng-bind="pin"></span></p>
</div>
</body>
the app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.show=false;
});
At first, a lot of used ng-init directive commonly not best practice. Take a look angular's advice.
So that reason, I think initializing value have to be placed in controller.
Check it out this plunker.
ng-init is for having initial data, But it also gets unnecessary logic into the Template
You can do the same Initializing in the Controller like:
app.controller('MainCtrl', function($scope) {
$scope.user = {
firstName: 'Ritu',
address: 'Uttam Nagar',
city: 'West Delhi',
state: 'Delhi',
pin: '110045'
}
$scope.show=false; });
And bind the user object in the view like:
<body ng-controller="MainCtrl">
Name: <span>{{user.firstName}}</span>
Address: <span>{{user.address}}</span>
City: <span>{{user.city}}</span>
State: <span>{{user.state}}</span>
pin: <span>{{user.pin}}</span>
<button data-ng-click="show=!show">Click and Show</button>
<div ng-show="show">
<p>Name <span ng-bind="user.firstName"></span></p>
<p>Address <span ng-bind="user.address"></span></p>
<p>City <span ng-bind="user.city"></span></p>
<p>State <span ng-bind="user.state"></span></p>
<p>pin <span ng-bind="user.pin"></span></p>
</div>
</body>
This simplifies the Code and keeps the Template clean
Here is a plunker

Push To Angular JS Array

I'm running into a strange issue when executing the .push() method on an angular js collection. In the console I can see the object is added, but I cannot actually see it added to the list.
$scope.discountCodes.push({
discountCodeId: 0,
name: $scope.discountModel.name,
code: $scope.discountModel.code,
codeValue: $scope.discountModel.codeValue,
valueType: $scope.discountModel.valueType,
startDate: $scope.discountModel.startDate,
endDate: $scope.discountModel.endDate,
isActive: "True"
});
I have a simple repeater combined with a template
<div ng-repeat="discount in discountCodes" ng-include="getTemplate(discount)">
</div>
<script type="text/ng-template" id="display">
<div class="row">
<div class="col-md-3">
<span>Name:<br />{{discount.Name}}</span>
</div>
<div class="col-md-2">
<span>Code:<br />{{discount.Code}}</span>
</div>
<div class="col-md-2">
<span>Value:<br />{{discount.CodeValue}}</span>
</div>
<div class="col-md-2">
<span>Active:<br /></span>
<i class="icon-circle green-fill"
ng-show="discount.IsActive">
</i>
<i class="icon-circle red-fill"
ng-show="!discount.IsActive">
</i>
</div>
<div class="col-md-2"><br />
<i class="icon-edit icon-2x"></i>
</div>
</div>
</script>
This is the method:
$scope.discountModel.formSubmit = function (item, event) {
$scope.alertMessageContainerVisible = false;
if ($scope.frmDiscountForm.$valid) {
var dataObject = {
discountCodeId: 0,
name: $scope.discountModel.name,
code: $scope.discountModel.code,
codeValue: $scope.discountModel.codeValue,
valueType: $scope.discountModel.valueType,
startDate: $scope.discountModel.startDate,
endDate: $scope.discountModel.endDate,
isActive: "True"
};
action = "NEW";
$scope.discountCodes.push(dataObject)
});
}
}
Any ideas are helpful, I am new to Angular JS so be easy on me :)
I created a very simple version of this below:
http://plnkr.co/edit/qJDU7uiFleWIOjR5LYFh
It looks like you might be updating the collection outside of the Angular context. If so, you'll need to use $scope.$apply() for Angular to see your changes.
Turned out to be a stupid mistake! I had my controller defined in the body and in the div, so it was in two places. Now everything is working good!
Thanks all, it was good learning experience

AngularJS: find the index position from directive with data in ng-init statements

How I can do to show the correct data when I click on that item. I have my directive which compile a template when I click and I want that when you click on that element data show me that element and not the last value that I have in my json. For example, I have 1 2 3 item and when I click on the first item I want to display the data of the first element and not the data of the last element.
Html containing the attribute ng-init with data:
<li ng-init='product = {id: "<%=product.id%>", brand: "<%=product.name_short%>", descriptionExcerpt: "", price: "", priceBefore: "", priceDiscount: "", mainImage: "<%=raw(main_image.url(:huge))%>", masterVariant: {id: "<%=product.master.id%>"}, variants: [{id: "0", name: "ASDasd", price: "£123", available: true }, {id: "1", name: "ASDwegwagasd", price: "£13", available: false }]}' preview-product index="$index">
<div class="sd-product-container">
<div class="sd-product-image">
<a itemprop="image" href="<%= url %>">
<img src="<%= raw(image_url) if image_url %>" itemprop="image" alt="<%= product.name %>" width="244" height="244" />
</a>
<div class="sd-product-options">
</div>
</div>
<div class="sd-product-description">
<h4><%= product.brand.name.html_safe %></h4>
<span>
<%= link_to truncate(product.name_short, length: 100), url, class: 'product-name', itemprop: 'name' %>
</span>
<% if product.teaser.present? %>
<span class="sd-small-caps">
<%= link_to strip_tags(product.teaser), url %>
</span>
<% end %>
<%= render partial: 'spree/products/price', locals: { product: product, current_currency: current_currency } %>
</div>
</div>
</li>
My Directive:
(function (){
"use strict";
var app = angular.module('quickPreview');
app.directive('previewProduct', function ($compile,$templateCache) {
return {
restrict: 'A',
scope: {
index: '#'
},
link: function(scope, element, attrs) {
element.bind('click', '.sd-click-preview', function (){
var preview = angular.element($templateCache.get('quickpreview.html'));
var cpreview = $compile(preview);
element.append(preview);
cpreview(scope);
console.log(cpreview(scope));
});
}
};
});
}(window, window.angular));
My template where I need to paint the data
<script type="text/ng-template" id="quickpreview.html">
<div class="content-preview">
<div class="content-preview-inner">
<span class="full-preview"></span>
<span class="close-preview"></span>
<div class="block block-left left">
<div class="content-tabs">
<div class="tabs-content vertical">
<div class="content active" id="panel1">
<div class="content-details">
<div class="details">
<h3 class="title-product">{{product.brand}}</h3>
<h2 class="short-desc">{{product.descriptionExcerpt}}</h2>
<div class="block-price">{{product.descriptionExcerpt}}</div>
</div>
</div>
<div class="content-img">
<div class="main-img">
<img ng-src="{{product.mainImage}}" alt="">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</script>
Solution found!
With just read some documentation about angular I could figure it out
just had to add this line in my directive:
scope: true
When using Isolated Scope with Attributes.
Here I leave a link where they explain Isolated Scope With Attributes

Resources