i am having a problem with ng-model .When i am adding tag from suggestion list its not updating model value until i am not deleting tags and adding again.In my project its working fine but for plunker only its happening.Please check this out and help me..
thank you..
Here is my html:-
<tags-input ng-model="tags2" display-property="tagName" on-tag-added="getTags()" id="target">
<auto-complete source="loadTags($query)" min-length="2"></auto-complete>
</tags-input>
<p>{{tags2}}</p>
Here is my js:-
var app = angular.module('myApp', ['ngTagsInput', 'ui.bootstrap']);
app.controller(
'myController',
function($scope, $http) {
$scope.tagsValues =[];
$scope.loadTags = function(query) {
return $http.get('tags.json');
};
$scope.getTags = function() {
$scope.tagsValues = $scope.tags2.map(function(tag) {
return tag.tagId;
});
alert(" Tag id is :"+ $scope.tagsValues);
};
});
Here is my plunker:-
http://plnkr.co/edit/6Mr2qk2S2RvGJLevf2UI?p=preview
All you have to do to make this work, is define and initialize the variable $scope.tags2 first:
var app = angular.module('myApp', ['ngTagsInput', 'ui.bootstrap']);
app.controller(
'myController',
function($scope, $http) {
$scope.tagsValues = '';
$scope.tags2 = [];
$scope.loadTags = function(query) {
return $http.get('tags.json');
};
$scope.getTags = function() {
$scope.tagsValues = $scope.tags2.map(function(tag) {
return tag.tagId;
});
alert(" Tag id is :"+ $scope.tagsValues);
};
});
See my plunker: http://plnkr.co/edit/Y3f8kLBnexOXg5gwmldL?p=preview
Related
I would like to access the input field value inside a variable that could be used in AngularJS so that I could add it to a string with the help of which I could call a rest api.
kindly help.
<body ng-app="myApp">
<div ng-controller="myCtr">
<form name="myForm">
<input type="text" ng-model='pinCode' id="zip" onBlur="myZipcode">
{{city}}
{{state}}
</form>
</div>
<script>
var zip;
var pat1;
function myZipcode(){
zip = document.getElementById("zip").value;
pat1 = 'http://ziptasticapi.com/'+zip;
}
var myApp = angular.module('myApp' , []);
myApp.controller('myCtr', function($scope, $http){
var path = 'http://ziptasticapi.com/12345'
$http.get(pat1).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;});
});
</script>
</body>
Here in http.get service if I use path variable instead of pat1 it works.
Another thing that I want the state and city to come dynamically without the form to be submitted and to be called from an REST API. That is why I am trying to get the input value inside a variable to accomplish the task
No need to define extra var for pinCode because of you used ng-model so you can access pinCode from your controller. Also should use ng-blur instead of onBlur.
You can use like
HTML:
<input type="text" ng-model='pinCode' id="zip" ng-blur="myZipcode()">
Controller:
var myApp = angular.module('myApp' , []);
myApp.controller('myCtr', function($scope, $http){
$scope.pinCode= ''; // defaulr empty
var path = 'http://ziptasticapi.com/';
$scope. myZipcode = function() {
$http.get(path + $scope.pinCode).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;
});
};
});
You should not access html elements from your controller code. Angular's two way data-binding already transfers the form input's value into the $scope.pinCode variable. So you only need some action to trigger your server call. See this sample in the angular docs: https://docs.angularjs.org/api/ng/directive/ngSubmit
myApp.controller('myCtr', function($scope, $http) {
$scope.doCall = function() {
// $scope.pinCode() is set here
$scope.$http.get(...).then(
function(response) {
$scope.city = response.data.city; // or similar
}
);
}
});
just bind zip and pat1 on controller's scope
Controller:
myApp.controller('myCtr', function($scope, $http){
$scope.zip = document.getElementById("zip").value || 0;
$scope. pat1 = 'http://ziptasticapi.com/'+ $scope.zip || '';
$scope.myZipcode();
});
and then in zipcode
Zipcode function:
$scope.myZipcode = function myZipcode(){
$scope,zip = document.getElementById("zip").value;
$scop.pat1 = 'http://ziptasticapi.com/'+zip;
$http.get(pat1).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;}
}
Complete code:
<body ng-app="myApp">
<div ng-controller="myCtr">
<form name="myForm">
<input type="text" ng-model='pinCode' id="zip" ng-blur="myZipcode">
{{city}}
{{state}}
</form>
</div>
<script>
myApp.controller('myCtr', function($scope, $http){
$scope.zip = document.getElementById("zip").value || 0;
$scope. pat1 = 'http://ziptasticapi.com/'+ $scope.zip || '';
$scope.myZipcode();
$scope.myZipcode = function myZipcode(){
$scope,zip = document.getElementById("zip").value;
$scop.pat1 = 'http://ziptasticapi.com/'+zip;
$http.get(pat1).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;}
}
});
</script>
</body>
I've created a simple To Do App and while working on it I felt like I will end up placing too much code into my Controller and will eventually get messy and hard to read. I want to know how can I move my functions into factories so that my code can look somewhat cleaner.
Here is my JS:
angular.module('toDoApp', [])
.controller('toDoCtrl', function($scope){
//set $scope variables
$scope.tasks = [];
$scope.submitTask = function(){
$scope.tasks.unshift($scope.enteredTask);
$scope.enteredTask = '';
};
$scope.removeTask = function(task) {
var i = $scope.tasks.indexOf(task);
$scope.tasks.splice(i, 1);
};
})
.factory('toDoFactory', ['$http', function($http){
return function(newTask) {
};
}])
Here is the HTML if needed:
<form ng-submit="submitTask()">
<!-- task input with submit button -->
<label>Task: </label>
<input type="text" placeholder="Enter Task" ng-model="enteredTask" required>
<button>Submit</button>
</form>
<div>
<!-- create unordered list for task that are submitted
need check boxes -->
<ul>
<li ng-repeat="task in tasks">
{{ task }}
<button ng-click="removeTask()">x</button>
</li>
</ul>
</div>
As you can see I kinda started the factory but just don't know how to go about it.
Any suggestions will be greatly appreciated.
You will need to inject your factory inside controller and then use the methods defined in the factory from the controller:
angular.module('toDoApp', [])
.controller('toDoCtrl', function($scope, toDoFactory){
//set $scope variables
$scope.tasks = [];
$scope.submitTask = function(){
toDofactory.submittask(); //Just for demo.Passin your parameters based on your implementation
};
$scope.removeTask = function(task) {
var i = $scope.tasks.indexOf(task);
$scope.tasks.splice(i, 1);
};
})
.factory('toDoFactory', ['$http', function($http){
var methods = {};
methods.submittask = function(){
//your logic here
};
methods.removetask = function(){
//your logic here
}
return methods;
}])
var app = angular.module('toDoApp', []);
app.controller('toDoCtrl', function($scope, toDoFactory){
$scope.tasks = [];
toDoFactory.get = function(){
}
toDoFactory.delete = function(){
}
toDoFactory.update = function(){
}
});
app.factory('toDoFactory', ['$http', function($http){
var todo = {};
todo.get = function(){
};
todo.delete = function(){
};
todo.update = function(){
}
return todo;
}]);
This is simple architecture, you can add more logic,
Make sure you know about dependency injection(DI)
Here is the answer for those that want to see what the end result will look like when all the code is plugged in. Thanks again for the answers as it was able to guide me in the right direction.
.controller('toDoCtrl', function($scope, toDoFactory){
$scope.tasks = toDoFactory.tasks;
$scope.submitTask = function(){
toDoFactory.submitTask($scope.enteredTask);
$scope.enteredTask = '';
};
$scope.removeTask = function(task) {
toDoFactory.removeTask();
};
})
.factory('toDoFactory', ['$http', function($http){
var toDo = {
tasks: [],
enteredTask: '',
submitTask: function(task){
toDo.tasks.unshift(task);
},
removeTask: function(task) {
var i = toDo.tasks.indexOf(task);
toDo.tasks.splice(i, 1);
}
};
}])
I'm trying to make a custom directive to create a menu where the href value changes depending on the family.id value which I got via service.
I'm trying to use that family.id value of each element in ng-repeat to query a new value through a service and change the href depending on that value
product.html
<ul class="list" custom-href categories="getfamilies"></ul>
href.js
(function(){
var app = angular.module('hrefDirective',['productsService']);
app.directive('customHref',['productsService', function(productsService) {
return {
restrict: 'EA',
transclude: false,
scope: {
categories: '='
},
template: '<li ng-repeat="family in categories"><p><a ng-bind="family.name" ng-href="{{newHref}}"></a></p></li>',
link : function($scope,$element, $attrs){
productsService.finalFamilies(family.id).then(function(data){
if(data == 0){
$scope.newHref = '#/product/';
}else{
$scope.newHref = '#/product/{{family.id}}';
}
});
}
};
}]);
})();
products.js
(function(){
var app = angular.module('productosController',['productsService']);
app.controller('ProductsFamiliesController', function($scope, productosService){
productsService.getFamilies().then(function(data){
$scope.getfamilies = data.data;
});
});
})();
services.js
(function(){
var app = angular.module('productsService',[]);
app.factory('productsService', ['$http','$location', function($http, $location){
var webServiceUrl = 'my url'
var products = [];
products.getFamilies = function(){
return $http.get(webServiceUrl+'getFamilies');
};
products.finalFamilies = function(idFamily){
return $http.get(webServiceUrl+'getFinalFamiles?id'+ idFamily);
};
return products;
}]);
})();
Of course is not working...any clues...?
plnkr.co/edit/3N19E0KyeWW7wvsLOlkk?p=info
I have 2 controllers. I want to make a simple toggle where if a function is called it hides code in the other controller. Here is what I have...
Angular:
var app = angular.module('plunker', []);
app.factory('data', function () {
var fac = [];
fac.hideIt = function (hide) {
console.log(hide)
if (hide != null)
return true;
else
return false;
};
return fac;
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
console.log(data.hideIt()); //its false
$scope.hide = data.hideIt();
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function () {
var hide = true;
data.hideIt(hide);
console.log(data.hideIt(hide)) //now it is true
}
});
HTML:
<div ng-controller="MainCtrl">
<div ng-if="hide == false">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
Link to Plunkr:
http://plnkr.co/edit/zOAf5vGMTAd8A10NGiS1?p=preview
Is there no way to use a controller to hide code that is in another controller?
You dont need to use $emit, $rootScope.$broadcast or something else
in your code you asked to the factory the value of a local variable, you cant updates it because each time you start the method a new variable was created;
Here is a working example, hope it will help you
http://plnkr.co/edit/jBc3DJnzXNJUiVVwRAPw?p=preview
The factory declare some useful methods like updates and gets hide value
app.factory('HideFactory', function () {
var prototype = {};
var hide = false;
prototype.getDisplayMode = function() {
return hide;
}
prototype.hideIt = function (val) {
hide = typeof val == 'boolean' ? val : false;
return val;
};
return prototype;
});
The controllers declare some variables which are a reference to the factory methods
app.controller('MainCtrl', ['$scope', 'HideFactory',function($scope, HideFactory) {
$scope.name = 'World';
$scope.isHide = HideFactory.getDisplayMode;
}]);
app.controller('SecCtrl', ['$scope', 'HideFactory', function($scope, HideFactory) {
$scope.isHide = HideFactory.getDisplayMode;
$scope.hideAbove = function() {
HideFactory.hideIt(true);
}
}]);
And the html, the ng-if directive call the isHide method, linked to the getDisplayMode method of the factory
<body>
<div ng-controller="MainCtrl">
<div ng-if="!isHide()">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
</body>
You're about halfway there with your factory, you have most of a setter but not a getter. Here's what I'd change.
Factory:
app.factory('data', function () {
var fac = [];
var state = false;
fac.hideIt = function (hide) {
state = hide;
};
fac.hidden = function() {
return state;
}
return fac;
});
Controller:
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
$scope.hide = data.hidden;
});
HTML:
<div ng-controller="MainCtrl">
<div ng-hide="hide()">
<p>Hello {{name}}!</p>
</div>
</div>
Forked Plunker
please see here: http://plnkr.co/edit/3NEErc0zUpXlb1LarXar?p=preview
var app = angular.module('plunker', []);
app.factory('data', function() {
var fac = [];
var _hide = {};
hideIt = function(hide) {
console.log("from fact " + hide)
if (hide !== null) {
_hide.state = true;
return _hide;
} else
_hide.state = false;
return _hide;
};
return {
fac: fac,
hideIt: hideIt,
hide: _hide
};
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
//console.log(data.hideIt()); //its false
$scope.hide = data.hide;
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function() {
var hide = true;
data.hideIt(hide);
}
});
HTML:
<div ng-if="hide.state != true">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE</div>
</div>
</body>
You want to use $emit.
function firstCtrl($scope){
$scope.$on('someEvent', function(event, data) { console.log(data); });
}
function secondCtrl($scope){
$scope.$emit('someEvent', [1,2,3]);
}
THE SITUATION:
I am exploring AngularJS by re-building a former project with it. I am using the angularjs-rails gem version 1.2.16. I have a page were I make an API call that returns an array of objects of music events. CONTROLLER:
d2jiveControllers.controller('VenueResultsCtrl', ['$scope','$http','$routeParams',
'$compile', '$sce', 'spotifyFactory', function($scope, $http, $routeParams,
$compile, $sce, spotifyFactory){
"use strict";
var venueId = $routeParams.venueId;
var baseUrl = 'http://api.songkick.com/api/3.0/venues/';
var apiKey = '/calendar.json?apikey=************';
var url = baseUrl + venueId + apiKey + '&jsoncallback=JSON_CALLBACK' ;
var init = function(url){
$http.jsonp(url)
.success(function (data) {
$scope.events = data.resultsPage.results.event;
console.log(data);
}).
error(function(){
console.log('failure');
});
};
$scope.tracks = function(artistName){
var artistTracks = spotifyFactory.getArtistTracks(artistName);
var spotifyIframe = $('spotifyIframe');
$scope.show_tracks = $sce.trustAsHtml("<iframe src='https://embed.spotify.com/?uri=spotify:trackset:Playlist:"+artistTracks.spotifyTracks + "'"+
"&theme=white'width='300' height='300'frameborder='0' allowtransparency='true'></iframe>")
console.log(artistTracks)
};
init(url);
}]);
I list them out using ng-repeat and attach an ng-click to each listing. HTML TEMPLATE:
<div class="eventContainer row" ng-controller="VenueResultsCtrl">
<div ng-repeat="event in events">
<h4>
{{event.displayName}}
</h4>
<p>
Buy Tickets
</p>
<div ng-repeat="artist in event.performance">
<button ng-click="tracks(artist.displayName)">Discover
{{artist.displayName}}<br> -- {{artist.billing}}</button><br><br>
<div ng-bind-html="show_tracks"></div>
</div>
</div>
</div>
On click I want to make another API call to Spotify to get back track IDs that I then place into an iframe. To do this I tried both making the call in a directive and factory:
DIRECTIVE:
d2jive.directive('getSpotifyTracks', [function () {
// <div get-spotify-tracks="artist.displayName"></div>
var spotifyUrl = "http://ws.spotify.com/search/1/track.json?callback=JSON_CALLBACK&q=";
return {
restrict: 'AEC',
scope: {
artistName: '='
},
templateUrl: 'assets/d2jive/templates/artistTracks.html',
controller: ['$scope', '$http', function($scope, $http){
$scope.getTracks = function(artistName){
$http.jsonp(spotifyUrl + encodeURIComponent(artistName))
.success(function (data) {
var trackArray = [];
var tracks = data.tracks.slice(0,9);
for (var track in tracks){
grabbedTrack = tracks[track].href.slice(
14, tracks[track].href.length);
trackArray.push(grabbedTrack);
}
$scope.artistTracks = trackArray;
console.log(data);
});
};
}],
link: function(scope, element, attrs, ctrl){
scope.$watch('artist.displayName', function(displayName){
if (displayName){
scope.getTracks(displayName);
}
})
}
}
}]);
FACTORY::
d2jive.factory('spotifyFactory', ['$http','$q', function($http, $q){
var factory = {}
factory.getArtistTracks = function(artistName){
var tracks = {}
var spotifyUrl = "http://ws.spotify.com/search/1/track.json?q=";
var deferred = $q.defer();
var getTracks = function(artistName){
$http.get(spotifyUrl + encodeURIComponent(artistName))
.success(function (data) {
deferred.resolve(data);
});
return deferred.promise;
};
// tracks.spotifyTrakcs = getTracks(artistName);
var spotifyTracks = getTracks(artistName);
spotifyTracks.then(function(result){
var trackArray = [];
var tracks = result.tracks.slice(0,9);
for (var track in tracks){
grabbedTrack = tracks[track].href.slice(
14, tracks[track].href.length);
trackArray.push(grabbedTrack);
}
tracks.spotifyTracks = trackArray;
});
return tracks;
}
return factory;
}]);
THE PROBLEM:
I can't find a way to append the iframe HTML to a particular item and not each event that is listed. The directive didn't seem to work because it loaded right away and slowed down the app way too much. That is why I went with a Factory to make the API call to Spotify and append the iframe.
THE GOAL:
On ng-click make API call to Spotify, return the track ID's, insert them into the iframe, and then insert that right below the clicked item not below all of the items.
Any help will be much appreciated! Thanks.
Inside the $watch in the link function of your directive, return early on equality between newVal and oldVal parameters:
link: function(scope, element, attrs, ctrl){
scope.$watch('artist.displayName', function(displayName, oldVal){
if (displayName === oldVal) { return }
if (displayName){
scope.getTracks(displayName);
}
})
}
That should prevent getTracks() from being called as soon as the directive links.