Angular assign value from directive to object - angularjs

I have this custom directive:
var geo = angular.module('Geo', ['Gealocation']);
function SearchForm($scope){
$scope.location = '';
$scope.doSearch = function(){
if($scope.location === ''){
alert('Directive did not update the location property in parent controller.');
} else {
alert('Yay. Location: ' + $scope.location);
}
};
}
/* Directives */
angular.module('Gealocation', []).
directive('googlePlaces', function(){
return {
restrict:'E',
replace:true,
// transclude:true,
scope: {location:'='},
template: '<input id="google_places_ac" name="google_places_ac" type="text" class="form-control"/>',
link: function($scope, elm, attrs){
var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
google.maps.event.addListener(autocomplete, 'place_changed', function() {
var place = autocomplete.getPlace();
$scope.location = [place.geometry.location.lat(), place.geometry.location.lng()];
$scope.$apply();
});
}
}
});
geo.controller('SearchForm', SearchForm);
And in index.html i have few input and custom directive:
<input type="text" class="form-control" ng-model="meeting.topic"></input>
<input type="text" class="form-control" ng-model="meeting.when"></input>
<input type="text" class="form-control" ng-model="meeting.level"></input>
<input type="text" class="form-control" ng-model="meeting.describe"></input>
<google-places location=location></google-places>
<button ng-click="doSearch()" class="btn btn-large btn-primary">Search!</button>
and to display value(location with lat and lng) from directive i can do that by:
{{location}}
But how can i assign this location to something like that :
meeting.location
becouse i need to pass later object meeting

I solved this by:
In controller:
$scope.meeting = {
location: ''
};
In view:
{{meeting.location = location}}

Related

How to set ng-model variable from custom validation directive

How to call controller scope from angularjs directive outside link function
$scope is unknown provider here:
app.directive('checkId', function($parse,$scope, $http){//here $scope is unknown provider
return{
restrict:'A',
link: function(scope, element, attrs){
element.bind('change', function(){
var filteredLength = $parse(attrs.filtered)(scope);
console.log(filteredLength);
var newFilteredArray = scope.stateList.filter(function(values){
return values.toUpperCase() == scope.TRDetail.memberNo.toUpperCase();
});
if(filteredLength == 0){
console.log("if called");
scope.TRDetail.memberNo = "";
}else if(newFilteredArray.length == 0){
scope.TRDetail.memberNo = "";
};
scope.$apply();
thisIsCalled(scope.TRDetail.memberNo);
});
}
};
function thisIsCalled(someData){
if(someData == ""){
alert("NOT doing some $http srvices");
}else{
$http.post("SomeURL", someData).then(function(response, error){
if(error){
alert("sorry no data found" + error.message);
}else{
$scope.TRDetail.memberName = response.data;
}
});
};
};
});
HTML:
<div class="form-group col-md-3">
<label>MemberShip NO:<span ng-if="(stateList|filter:TRDetail.memberNo).length==0" style="color:red;">(nothing found)</span></label>
<input list="idList" class="form-control" name="browser"
ng-model="TRDetail.memberNo"
filtered="(stateList|filter:TRDetail.memberNo).length"
check-id>
<datalist id="idList">
<option ng-repeat="x in stateList">{{x}}</option>
</datalist>
</div>
<div class="form-group col-md-9">
<label>Member Name</label>
<input type="text" ng-disabled="true"
ng-model="TRDetail.memberName" class="form-control"
placeholder="type name here..">
</div>
I am unable to update TRDetail.memberName outside from link function.
any help, how to do?
tl; dr;
Use ngModel.$setViewValue
When a custom directive is combined with ng-model directive, the directive should use the ngModelController API:
app.directive('checkId', function($parse,$http){
return{
require: 'ngModel',
restrict:'A',
link: function(scope, element, attrs, ngModel){
̶e̶l̶e̶m̶e̶n̶t̶.̶b̶i̶n̶d̶(̶'̶c̶h̶a̶n̶g̶e̶'̶,̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶)̶{̶
ngModel.$viewChangeListeners.push(onChange);
function onChange(){
if (!ngModel.$modelValue) return;
var filteredLength = $parse(attrs.filtered)(scope);
console.log(filteredLength);
var newFilteredArray = scope.stateList.filter(function(values){
̶r̶e̶t̶u̶r̶n̶ ̶v̶a̶l̶u̶e̶s̶.̶t̶o̶U̶p̶p̶e̶r̶C̶a̶s̶e̶(̶)̶ ̶=̶=̶ ̶s̶c̶o̶p̶e̶.̶T̶R̶D̶e̶t̶a̶i̶l̶.̶m̶e̶m̶b̶e̶r̶N̶o̶.̶t̶o̶U̶p̶p̶e̶r̶C̶a̶s̶e̶(̶)̶;̶
return values.toUpperCase() == ngModel.$modelValue.toUpperCase();
});
if(filteredLength == 0){
console.log("if called");
̶s̶c̶o̶p̶e̶.̶T̶R̶D̶e̶t̶a̶i̶l̶.̶m̶e̶m̶b̶e̶r̶N̶o̶ ̶=̶ ̶"̶"̶;̶
ngModel.$setViewValue("");
}else if(newFilteredArray.length == 0){
̶s̶c̶o̶p̶e̶.̶T̶R̶D̶e̶t̶a̶i̶l̶.̶m̶e̶m̶b̶e̶r̶N̶o̶ ̶=̶ ̶"̶"̶;̶
ngModel.$setViewValue("");
};
̶s̶c̶o̶p̶e̶.̶$̶a̶p̶p̶l̶y̶(̶)̶;̶
̶t̶h̶i̶s̶I̶s̶C̶a̶l̶l̶e̶d̶(̶s̶c̶o̶p̶e̶.̶T̶R̶D̶e̶t̶a̶i̶l̶.̶m̶e̶m̶b̶e̶r̶N̶o̶)̶;̶
thisIsCalled(ngModel.$modelValue);
}
function thisIsCalled(someData){
if(someData == ""){
alert("NOT doing some $http srvices");
}else{
$http.post("SomeURL", someData)
.then(function(response){
ngModel.$setViewValue(response.data);
})
.catch(function(error) {
alert("sorry no data found" + error.status);
});
};
}
}
};
For more information, see
AngularJS ngModelController API Reference
Your function thisIsCalled(someData) is just not living inside your angular app. You should get access to the $scope element through the directive's controller:
angular.directive('checkId', function($parse, $scope, $http) {
return {
restrict: 'A',
link: //your link stuff
controller: myController
};
});
function myController($scope) {
//here you can access the scope
}

AngularJS how to bind the ng-model on $watch

I'm building an app using ionic framework and in my search module I'm using a library called ion-autocomplete https://github.com/guylabs/ion-autocomplete trying to bind the ng-model to my scope but I can't get it to bind.
Controller:
$scope.model = "";
$scope.callbackMethod = function (query) {
//scope.model doesn't bind
return PostService.SearchUser($scope.model, $localStorage.CurrentUser.auth_token, -1, -1)
.success(function (data) {
console.log(data);
})
.error(function(error) {
});
};
View:
//this derective is an input field
<ion-autocomplete ng-model="model" items-method="callbackMethod(query)" placeholder="Enter something"/>
Template:
var template = '<input type="search" class="ion-autocomplete-search" ng-model="searchQuery" placeholder="{{placeholder}}"/>'
Directive:
.directive('ionAutocomplete', function () {
return {
require: '?ngModel',
restrict: 'E',
template: '<input ion-autocomplete type="text" readonly="readonly" class="ion-autocomplete" autocomplete="off" />',
replace: true
}
});

How to access ng-model value in directive?

I created a directive for google map auto-complete. everything is working fine, but the problem is when I need to access the value of input and re-set it. it doesn't work. Here is code:
<div controller='mainCtr'>
<span click='reset(destination)'>Reset</span>
<div class='floatleft' style='width:30%;margin-right:40px;'>
<smart-Googlemaps locationgoogle='destination.From'></smart-Googlemaps>
<label>From</label>
</div>
</div>
In the directive:
angular.module('ecom').directive('smartGooglemaps', function() {
return {
restrict:'E',
replace:false,
// transclude:true,
scope: {
locationgoogle: '='
},
templateUrl: 'components/directives/autocomplete/googlemap-search.html',
link: function($scope, elm, attrs){
var autocomplete = new google.maps.places.Autocomplete($(elm).find("#google_places_ac")[0], {});
google.maps.event.addListener(autocomplete, 'place_changed', function() {
var place = autocomplete.getPlace();
// $scope.location = place.geometry.location.lat() + ',' + place.geometry.location.lng();
// console.log(place);
$scope.locationgoogle = {};
$scope.locationgoogle.formatted_address = place.formatted_address;
$scope.locationgoogle.loglat = place.geometry.location;
$scope.locationgoogle.locationText = $scope.locationText;
$scope.$apply();
});
}
}
})
Here is html for directive:
<input id="google_places_ac" placeholder="Please enter a location" name="google_places_ac" type="text" class="input-block-level" ng-model='locationText'/>
The directive works fine, I create a isolated scope(locationgoogle) to pass the information I need to parent controller(mainCtr), now in the mainCtr I have a function calld reset(), after I click this,I need to clean up the input make it empty. How Can I do it?
One way to access the value of the model in your directive from a parent controller is to put that on the isolate scope too and use the two-way binding flag = like you've done with the locationgoogle property. Try this:
DEMO
html
<body ng-controller="MainCtrl">
<button ng-click="reset()">Reset</button>
<smart-googlemaps location-text="locationText"></smart-googlemaps>
</body>
js
app.controller('MainCtrl', function($scope) {
// need to define model in parent and pass to directive
$scope.locationText = {
value: ''
};
$scope.reset = function(){
$scope.locationText.value = '';
}
});
app.directive('smartGooglemaps', function() {
return {
restrict:'E',
replace:false,
// transclude:true,
scope: {
locationgoogle: '=',
locationText: '='
},
// ng-model="locationText.value"
template: '<input id="google_places_ac" placeholder="Please enter a location" name="google_places_ac" type="text" class="input-block-level" ng-model="locationText.value"/>',
link: function($scope, elm, attrs){
// implement directive googlemaps logic, set text value etc.
$scope.locationText.value = 'foo';
}
}
})

Angularjs directive with bi-directional binding not working

I'm trying to write a simple directive that allows the user to edit a certain variable, but when i try to update the parent variable it doesn't work.
this is my html:
<p class="scene-field-name editable-name" editable="foo"> {{foo}} </p>
and the directive:
myApp.directive('editable', function ($window, $compile) {
return {
restrict: "A",
template: '<div class="editable-value" ng-hide="editorOn">{{value}} <a class="edit-a" ng-click="editorOn = true">edit</a></div>' +
'<div class="editable-editor" ng-show="editorOn">' +
'<input type="text" value="{{tmpValue}}" />' +
'<a ng-click="setValue()">OK</a>' +
'</div>',
scope: {
value: "=editable"
},
controller: function($scope) {
$scope.tmpValue = $scope.value;
$scope.editorOn = false;
$scope.setValue = function () {
$scope.value = $scope.tmpValue;
$scope.editorOn = false;
}
}
};
here it is in jsfiddle:
http://jsfiddle.net/4srx2z0c/2/
you can see that when clicking OK it doesn't save the value back in the parent scope...
You don't bind the input to tmpValue.
Instead of <input type="text" value="{{tmpValue}}" /> you should have <input type="text" ng-model="tmpValue" />.

Cannot access attribute that is a directive inside another directive's template

My custom directive is "testapp". I would like to access the value of "file-model" in its template, which would contain the file object to be uploaded. Whatever I do am not able to get the value, its displaying "undefined". Please suggest ways to solve this problem.
app.directive('testapp', function ($compile) {
return {
restrict: 'E',
scope: {
text: '#',
filem: '=fileModel'
},
require:'fileModel',
replace:true,
template: '<div class="col-xs-4" style="padding-left:0px"><div class ="jumbotron" id="Section1"><input type="text" name="id" id="section{{incr}}" placeholder="Section Heading" class="form-control"><form id="addLIForm1"><div ng-repeat="i in range(fileIncr) track by $index"><input type="text" name="file{{incr}}{{$index+1}}" id="file{{incr}}{{$index+1}}" class="form-control" placeholder="File Name" style="width:50%" ><input type = "file" id="path{{incr}}{{$index+1}}" file-model = "file{{incr}}{{$index+1}}"></div></form><a id="addMore" ng-click="addfile()" href="#">Add More File</a><a id="addMoreSec1" ng-click="add()" class="pull-right" href="#" ng-show="showValue">Add More Section</a></div></div>',
controller: function ($scope, $element,$window) {
$scope.incr=$window.globalIncr;
$scope.fileIncr=$window.globalfileIncr;
$scope.showValue=$window.globalsectionValue;
$scope.add = function () {
$window.globalsectionValue=false;
$window.globalIncr+=1;
$window.globalfileIncr=1;
var el = $compile("<testapp></testapp>")($scope);
$element.parent().append(el);
//alert($window.globalfileIncr);
//alert($element.parent().parent());
};
$scope.range=function(n)
{
return new Array(n);
}
$scope.addfile=function(){
alert($scope.filem);
$scope.fileIncr+=1;
$window.counterObject[$scope.incr] = $scope.fileIncr;
};
}
};
});

Resources