passing ng-model variable to an ng-click function - angularjs

in my case I generate "recent searches" links getting the anchor text from a list (ng-repeat="city in meteo.cityList").
Then I want to call a function passing the content of the ancor text, so I'm trying to use ng-model (ng-model='meteo.button') to get the value and ng-click to call the function (ng-click="meteo.search(meteo.button)")
<nav class="recent-cities">
<h3>Search History:</h3>
<a ng-repeat="city in meteo.cityList" ng-model='meteo.button' ng-click="meteo.search(meteo.button)" href="#">{{city}}</a>
</nav>
It doesn't work because ng-model does't get the value. I also wanted to pass "city" directly to the function but it doesn't work.
I guess the issue is about rendering but i can't figure out how.
Here is the entire code: http://codepen.io/tiuscia/pen/qqLQNd
I will appreciate any kind of help
thanks

use a div first
<div ng-repeat="city in meteo.cityList">
<a ng-model='city.button' ng-click="meteo.search(city.button)" href="#">{{city}}</a>

A way to solve this is using $event to retrieve the clicked element, so:
<a ng-model='city.button'
ng-click="meteo.search($event)" href="#">{{city}}</a>
Then you can do something like this in your controller function:
$scope.meteo.search = function(event) {
var city = event.target.text; // or event.currentTarget.text
// the rest of your code here...
another way is creating you own custom directive, so, you pass the city name (or city.button) to the directive.

Related

Why does not work ng-controller in HTML from AJAX?

I have HTML code that is returned from AJAX:
<div ng-controller="CounterPostsController">
<span ng-click="Do();"></span>
</div>
So, event ng-click does not work
In your CounterPostsController, do you have the Do() method defined and associated to the $scope variable?
i.e. $scope.Do() = function () {} or $scope.Do() = myCustomFunction;
You will need to associate your function to $scope in order the code above to work.
Hope this helps

angularjs: click on a tag to invoke a function and pass the current tag to it

I need to handle a click on a tag that enables the opening of a popover.
I try to figure out the best way to do this with angularjs and naturally used hg-click.
<div ng-repeat="photo in stage.photos"
ng-click="openPopoverImageViewer($(this))"
>
$scope.openPopoverImageViewer = function (source) {
alert("openPopoverImageViewer "+source);
}
The issue is that I cannot manage to pass the $(this) to it.
Q1) How to pass the jQuery element?
Q2) In addition, ng-click sounds
to require the function being part of the controller: is it possible
to invoke a function in the partial instead?
You need to stop "thinking in jQuery" :)
Like #oori says, you can pass in photo.
Or better yet, create a custom directive. Directives is the way to go when you need new functionality in your dom, like an element that you can click to open an overlay. For example:
app.directive('popOver', function() {
return {
restrict: 'AE',
transclude: true,
templateUrl: 'popOverTemplate.html',
link: function (scope) {
scope.openOverlay = function () {
alert("Open overlay image!");
}
}
};
});
You can then use this as a custom elemen <pop-over> or as an attribute on regular HTML elements. Here is a plunker to demonstrate:
http://plnkr.co/edit/P1evI7xSMGb1f7aunh3G?p=preview
Update: Just to explain transclusion: When you say that the directive should allow transclusion (transclude:true), you say that the contents of the tag should be sent on to the directive.
So, say you write <pop-over><span>This will be passed on</span></pop-over>, then the span with "This will be passed on" is sent to the directive, and inserted wherever you put your ng-transclude element in your template. So if your pop-over template looks something like this:
<div>
<ng-transclude/>
</div>
Then your resulting DOM after the template has compiled will look like this:
<div>
<span>This will be passed on</span>
</div>
Pass it "photo"
<div ng-repeat="photo in stage.photos" ng-click="openPopoverImageViewer(photo)">
or the current $index
<div ng-repeat="photo in stage.photos" ng-click="openPopoverImageViewer($index)">

Rendering dynamic HTML(angularjs content) content after ajax call in AngularJS

I am new to Angular getting stuck after making ajax call. How do I render/compile the html content once you inject in DOM so that I can still use the AngularJs functions.
Due to the way my backend is set up I have to get content via ajax ($http). And I am making the app without jQuery. I tried $compile and $apply but didn't work. What am I missing here.
I have the code set up at http://jsfiddle.net/rexonms/RB7FQ/3/ . I want the second div content to have the same properties as the first div.
HTML
<div ng-controller="MyCtrl" class="section">
<input ng-model="contentA">
<div>
And the input is: {{contentA}}
</div>
</div>
<div ng-controller="MyAjax" class="section">
<div id="dumpAjax">
{{ajaxData}}
</div>
<button ng-click=getajax()> Get Ajax</button>
</div>
SCRIPT
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
}
function MyAjax($scope){
var data = '<input ng-model="contentB">{{contentB}}';
$scope.getajax = function(){
$scope.ajaxData = data;
}
}
Thanks in advance.
ng-bind-html-unsafe is not available 1.2 and later verison of angular...
so you should use ng-bind-html which creates a binding that will innerHTML the result of evaluating the expression into the current element in a secure way.
using $scope variable in your string make it unsafe, so you should use $sce.trustAsHtml but this time variables in your string cannot be bind because they will be not compiled...
basically you should compile your string in order to bind your variables. Here comes custom directives you can create a directive which can replace with ng-html-bind...
Writing a custom directive which extends ng-bind-html with some extra functions can be a solution...
here is my PLUNKER
and here is your updated JSFIDDLE with my solution...
Instead of {{ajaxData}}, you should use something like:
<div ng-bind-html-unsafe="ajaxData"></div>
However, you'd still need to set the proper model to bind the contentB and get it working.

Dynamic variable name directive attribute

I have a my-edit directive that has a value attribute expecting a scope variable to bind to.
<my-edit value="myVar"></my-edit>
is there any way to do something like this:
<my-edit value="{{varName}}"></my-edit>
where varName = "myVar"
I want to nest this directive in "my-listbox" directive that has a "text-field" attribute
<my-listbox ng-model="myList" text-field="itemProp"></my-listbox>
So I was trying use a template like:
<div>
<ul>
<li ng-repeat="item in items">
<my-edit value="item.{{textField}}"></my-edit>
</li>
</ul>
</div>
But obviously it doesn't work
I guess using a text binding is also not the solution.
Is a dynamic generated template for "my-listbox" the way to go here?
I tried that in the compile function but the didn't work that well because of the nested neRepeat directive. Should it by done using $compile in link function?
Thanks
This is something pretty cool about angular, it evaluated the string that you pass to the directive. This means that you can actually just do value="item[textField]" and that will work.
For instance if you had a controller with data like this:
$scope.data = {
test: 'test_val',
other: 'other_val'
};
$scope.val = 'test';
You could just pass it like this to your directive:
<directive value="data[val]"></directive>
That is set up like this:
scope: {
value: '='
},
And the isolate scope will have scope.value = 'test_val' and will update to 'other_val' just by changing the original controller val to 'other'
I made a fiddle where this is set up for you to play with.
Hope this helps!

Getting to bound data in Angular.js

Is there a way in angular to get binding back from a template?
In other words, if I have something like this:
<div ng-repeat="item in list">
<div>{{item.name}}</div>
<div>{{item.state}}</div>
</div>
would it be possible to change the item's state by clicking on it, because the repeated div would "remember" what item it was built from?
Yes, you can use the ng-click directive to trigger a method on the current scope:
// In your view's controller:
function MyCtrl($scope, MyList) {
// You probably have something like that already to
// populate your list, using a $resource or $http GET call.
// Here I use a $resource which would be defined on your module.
$scope.list = MyList.query()
$scope.setState = function(state) {
// "this" refers to the current scope
this.item.state = state
}
}
// And in your view:
<div ng-repeat="item in list">
<div>{{item.name}}</div>
<div ng-click="setState('whatever')">{{item.state}}</div>
</div>
Or you can simply set an expression such as ng-click="item.state='whatever'" directly on the div, although this is less testable - only in end-to-end tests - and less flexible, say you want to introduce validation or something).
HTH

Resources