AngularJS - scope not refreshing when change route - angularjs

At first sorry for subject name, I didn't knew how to call it. I was searching for an answer but found nothing helpful or didn't knew how to implement this in my little app. I'm learning AngularJS and i thought a "drink counter" will be good for beginning. So all my app is supose to do is when you click a drink icon it adds an item(type of drink and datetime when) and the problem is that it isn't refreshing the drink list when I change route to /#archive/ it only does when I refresh page, my code is:
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'myController',
templateUrl: 'Views/home.html'
})
.when('/archive',
{
controller: 'myController',
templateUrl: 'Views/archive.html'
})
.otherwise({ redirectTo: '/' });
});
myApp.factory('myFactory', function () {
var saved = localStorage.getItem('myData');
var drinks = (localStorage.getItem('myData') !== null) ? JSON.parse(saved) : [];
localStorage.setItem('myData', JSON.stringify(drinks));
var factory = {};
factory.getDrinks = function () {
return drinks;
};
return factory;
});
var controllers = {};
controllers.myController = function ($scope, myFactory, $filter) {
$scope.drinks = [];
init();
function init() {
$scope.drinks = myFactory.getDrinks();
$scope.beerDrinked = $filter('filter')($scope.drinks, 'beer').length;
}
$scope.nowDrinking = function (what) {
$scope.drinks.push({
drinkDate: new Date(),
what: what
});
localStorage.setItem('myData', JSON.stringify($scope.drinks));
};
}
myApp.controller(controllers);
Yes, sure. This is my HTML in archive:
<ul class="drinked" data-ng-repeat="drink in drinks | orderBy: 'drinkDate':true track by $index">
<li class="{{ drink.what }}"><span class="date">{{ drink.drinkDate | date: 'EEEE, d MMMM yyyy' }}</span><span class="time">{{ drink.drinkDate | date: 'HH:mm:ss'}}</span></li>
</ul>
And this is in home:
<span data-ng-bind="beerDrinked"></span>
beer

if you want to refresh your html, you´ve to use ng-repeat, example:
<div class="drinks" data-ng-repeat="drink in drinks"></div>
I don´t know where the user have to click to refresh you page, but to do this you´ve to use data-ng-click directive, example:
<button data-ng-click="addDrink(someDrink)"></button>
So in your controller should be like this, example:
app.controller('MyController', function ($scope) {
$scope.drinks = [];
$scope.addDrink= function (drink) { //note that you don´t need(and don´t should) to pass your drink by parameter...
$scope.drinks.push(drink);
}
});

here, put your ng-repeat inside your li element, like this:
<ul class="drinked">
<li data-ng-repeat="drink in drinks | orderBy: 'drinkDate':true track by $index" class="{{ drink.what }}"><span class="date">{{ drink.drinkDate | date: 'EEEE, d MMMM yyyy' }}</span><span class="time">{{ drink.drinkDate | date: 'HH:mm:ss'}}</span></li>
</ul>
Try it!

Related

Restangular / Json-ld | I can get the data, but I can't show them

I'm new in Angular and need your help.
With my team, we made a PHP REST API in Symfony that we want to connect to an Angular client.
I already have the Angular app..
I can see in my XHR requests that i actually get the entities and their properties (users).
But in my view, i tried some {{ user.name }} with ng-repeat but it dosen't show anything.
Datas are sent in Json-ld and we use Restangular to read them.
Here some code :
app.js :
angular
.module('frontApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'restangular'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.otherwise({
redirectTo: '/'
});
})
.config(['RestangularProvider', function (RestangularProvider) {
// The URL of the API endpoint
RestangularProvider.setBaseUrl('http://localhost:8000');
// JSON-LD #id support
RestangularProvider.setRestangularFields({
id: '#id'
});
RestangularProvider.setSelfLinkAbsoluteUrl(false);
RestangularProvider.setResponseExtractor(function(response) {
var newResponse = response;
if (angular.isArray(response)) {
angular.forEach(newResponse, function(value, key) {
newResponse[key].originalElement = angular.copy(value);
});
} else {
newResponse.originalElement = angular.copy(response);
}
return newResponse;
});
// Hydra collections support
RestangularProvider.addResponseInterceptor(function (data, operation) {
// Remove trailing slash to make Restangular working
function populateHref(data) {
if (data['#id']) {
data.href = data['#id'].substring(1);
}
}
// Populate href property for the collection
populateHref(data);
if ('getList' === operation) {
var collectionResponse = data['hydra:member'];
collectionResponse.metadata = {};
// Put metadata in a property of the collection
angular.forEach(data, function (value, key) {
if ('hydra:member' !== key) {
collectionResponse.metadata[key] = value;
}
});
// Populate href property for all elements of the collection
angular.forEach(collectionResponse, function (value) {
populateHref(value);
});
return collectionResponse;
}
return data;
});
}])
;
main.js :
angular.module('frontApp')
.controller('MainCtrl', function ($scope, Restangular) {
$scope.ami1 = Restangular.one('amis',1).get();
$scope.test ='Test';
var amis = Restangular.all('amis');
amis.getList().then(function (ami) {
$scope.ami = ami;
});
});
main.html:
<div class="jumbotron">
<p>Liste d'amis :</p>
{{ ami1.nom }}
{{ test }}
<div ng-repeat="ami in amis" id="{{ ami['#id'] }}" class="row marketing">
<h1>{{ ami.nom }}</h1>
<h2>{{ ami.prenom }}</h2>
<h3>{{ ami.id }}</h3>
</div>
chrome console
Thanks for helping!
I found by myself, here is the code :
<div ng-repeat="ami in amis" id="{{ ami['#id'] }}" class="row marketing">
<h1>Nom: {{ ami.nom }}</h1>
<h2>Prenom: {{ ami.prenom }}</h2>
<h3>Date de naissance: {{ ami.dateNaissance }}</h3>
<h4>Telephone(s): </h4>
<div ng-repeat="telephone in ami.telephones" id="{{ telephone['#id'] }}">
{{ telephones[$index].numero }}
</div>
</div>
in your controller ...
$scope.amis = Restangular.all('amis').getList();
if that doesn't work ...
Restangular.all('amis').getList().then(function(response) {
$scope.amis=response;
}).catch(function(error) {
console.log(error);
})
Ok now i have another issue.
I have all of my 'ami' and their properties so it's really great, but my 'ami' have many 'telephone' ids in it.
What i try to do is to have my 'ami' 'numero' from 'telephone' with this telephone id.
i can list all of my 'amis' with telephon id in it, and all of my 'telephones' with the numeros in it.
Thanks angain :)

Firebase child_added and ng-repeat

I used child_added and ng-repeat to display a list of statuses, this part worked fine, but when I click on one of the statuses in the list i am sent to tab/statuses/ instead of going to tab/statuses/:statusid. Any help would be much appreciated.
app.js
.state('tab.statuses', {
url: "/statuses",
views: {
'tab-statuses': {
templateUrl: "templates/statuses.html",
controller: "StatusesController"
}
}
})
.state('tab.status', {
url: "/statuses/:statusid",
views: {
'tab-statuses': {
templateUrl: "templates/status.html",
controller: 'StatusController'
}
}
})
statusescontroller
app.controller('StatusesController', function ($scope, $filter, $state, $ionicListDelegate, $ionicActionSheet, StatusesService) {
$scope.statuses = [];
var ref = new Firebase("https://app85.firebaseio.com/statuses");
ref.on("child_added", function(snapshot, prevChildKey) {
var status = snapshot.val();
$scope.statuses.push(status);
});
})
statuses.html
<ion-item ng-repeat="status in statuses" href="#/tab/statuses/{{status.$id}}" class="customItemSize mlSmallerFont item-icon-left item-icon-right">
<i class="icon ion-ios-person-outline"></i>
{{ status.update }}
</ion-item>
You seem to be borrowing some ideas from AngularFire, but don't have the code to implement them. As it currently is the {{status.$id}} in your HTML has no value.
To fix that you should either use AngularFire or populate a $id in your controller:
ref.on("child_added", function(snapshot, prevChildKey) {
var status = snapshot.val();
status['$id'] = snapshot.key();
$scope.statuses.push(status);
});
Note that this will only work when snapshot.val() is an object (so not when it's a primitive). But since that is the case in your snippet, this should work.

Angularjs ng-click inside ng-repeat

I'm trying to load a list of clickable news feed URLs in a dropdown-menu. When I use fixed addresses in view, it works fine but when I populate the addresses using controller, dropdown menu is fine but ng-click doesn't work as expected.
Here is jsfiddle of working version:http://jsfiddle.net/mahbub/b8Wcz/
This code works:
<ul class="dropdown-menu">
<li>ABC News
</li>
<li>CNN
</li>
</ul>
controller code:
var App = angular.module('RSSFeedApp', []);
App.controller("FeedCtrl", ['$scope', 'FeedService', function ($scope, Feed) {
$scope.loadButonText = "Select news channel";
$scope.loadFeed = function (e) {
Feed.parseFeed($scope.feedSrc).then(function (res) {
$scope.loadButonText = angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
});
}
App.factory('FeedService', ['$http', function ($http) {
return {
parseFeed: function (url) {
return $http.jsonp('//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSON_CALLBACK&q=' + encodeURIComponent(url));
}
}
}]);
This code does not:
<ul class="dropdown-menu">
<li ng-repeat =" newsChannel in channels">
{{newsChannel.title}}
</li>
</ul>
controller code:
App.controller("FeedCtrl", ['$scope', 'FeedService', function ($scope, Feed) {
$scope.loadButonText = "Select news channel";
$scope.loadFeed = function (e) {
Feed.parseFeed($scope.feedSrc).then(function (res) {
$scope.loadButonText = angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
});
}
$scope.channels = [
{
'src': 'http://www.abc.net.au/news/feed/45910/rss.xml',
'title': 'ABC News'
},
{
'src': 'http://rss.cnn.com/rss/cnn_topstories.rss',
'title': 'CNN'
}
];
}]);
App.factory('FeedService', ['$http', function ($http) {
return {
parseFeed: function (url) {
return $http.jsonp('//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSON_CALLBACK&q=' + encodeURIComponent(url));
}
}
}]);
TypeError: Cannot read property 'feed' of null
Any idea why the $scope.feedSrc doesn't get the feedSrc url?
Thanks
So I recommend using $parent for this. ng-repeat has it's own scope so when you say "feedSrc" it is looking on the ng-repeat scope for that data. "newsChannel" is available because that gets added by ng repeat but you will notice that is never added to your parent controller's $scope.
<ul class="dropdown-menu">
<li ng-repeat =" newsChannel in channels">
{{newsChannel.title}}
</li>
</ul>
As an aside, you might consider not doing assignments in the view like that, it is generally preferable to only assign variables in the controller and make sure that your HTML is read only
The problem is how you are passing arguments to your ng-click:
ng-click="$parent.feedSrc='{{newsChannel.src}}';..."
You don't need to wrap the prperty in handlebars...
ng-click="$parent.feedSrc='newsChannel.src';..."
should fix your problem.
I found a workaround. Added another parameter to loadFeed method.
<ul class="dropdown-menu">
<li ng-repeat =" newsChannel in channels">
{{newsChannel.title}}
</li>
</ul>
and here is the controller's new version:
App.controller("FeedCtrl", ['$scope', 'FeedService', function ($scope, Feed) {
$scope.loadButonText = "Select news channel";
$scope.loadFeed = function (e, feedUrl) {
Feed.parseFeed(feedUrl).then(function (res) {
$scope.loadButonText = angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
});
}
$scope.channels = [
{
'src': 'http://www.abc.net.au/news/feed/45910/rss.xml',
'title': 'ABC News'
},
{
'src': 'http://rss.cnn.com/rss/cnn_topstories.rss',
'title': 'CNN'
}
];
}]);
thanks to this post: ng-click inside ng-repeat

Deep linking in angularjs?

I am trying to learn deep linking in angular.
As I click on a link which is created with ng-repeat like on the exp below:
<ul ng-controller="ShowOrderController">
<li ng-repeat="car in cars"><a href="#ShowOrder/cars.indexOf(car)">
{{car.Brand}}</a>
</li>
</ul>
It doesn't display relevant detail of the clicked link
I understand that I am not linking that properly on my controller:
sampleApp.controller('ShowOrderController', function($scope, $http, $routeParams) {
$http.get('data.json').
success(function(data){
$scope.cars = data;
$scope.car_id = $routeParams.carId;
});
});
I just can't figure out or find any source that explains plainly how to create deep linking..
Exp: http://plnkr.co/edit/7D0UegRrtKPxrZ8zfxEL?p=preview
Thanks a lot in advance!
Try this. working demo
You may change the filter as like below
<div ng-controller="ShowOrderController" ng-repeat="car in cars | filter: { id: car_id } | limitTo:1">
I think you haven't defined the filter(i.e 'query1'). Take a look at the following code.
sampleApp.controller('ShowOrderController', function($scope, $http, $routeParams) {
$http.get('data.json').
success(function(data){
$scope.cars = data;
});
$scope.car_id = $routeParams.carId;
id=$scope.car_id;
}).filter('query1',function(){
return function(array){
if(array){
for(var i in array){
if(array[i].id===Number(id)){
return [array[i]];
}
}
}
}
});
And the working plunker is here plunckr .

AngularJS : Setting languages in angular-translate from Controller or Service

I am interested in using angular-translate.
Due to a lot of setup calls that happen initially on startup, I cannot provide the language json during config. Nor is it possible to use the async loader.
I need to be able to specify the languages from a controller or service at a later point.
$translateProvider.translations(.., ...) is the call to use, but $translateProvider isn't available in controllers or services, but seemingly only at config.
$translate doesn't seem to have the ability to load a language JSON.
Is there any workaround?
First inject $translate into your controller.
app.controller('MainCtrl', function($scope, $state, $translate) {});
Then you can get and set current language with $translate.use().
var lang = $translate.use(); // holds current lang
$translate.use(lang); // sets lang to use
If you need to add new translations after config, then you can use partial loaders.
// config example
app.config(function($translateProvider, $translatePartialLoaderProvider){
// "known" translations here, in {lang}.main.json, if any
$translatePartialLoaderProvider.addPart('main');
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: '/path/to/files/{lang}.{part}.json'
});
});
// controller
app.controller('MainCtrl', function($scope, $translate, $translatePartialLoader){
$translatePartialLoader.addPart('translation');
$translate.refresh();
$translate.use('en');
});
// en.translation.json
{ "KEY" : "Value", ... }
If that is not dynamic enough, then you can always do the translation on-the-fly.
// config
app.config(function($translateProvider, $translatePartialLoaderProvider){
$translateProvider.preferredLanguage('en');
$translateProvider.translations('en',{
'TITLE': '{{ title }}',
'SUBTITLE': '{{ subtitle }}',
'STATIC': 'This is static'
});
});
// controller
app.controller('MainCtrl', function($scope, $translate){
$scope.dynamic = {
'title': 'This is my header',
'subtitle': 'My subtitle'
};
});
// template
<pre>{{ 'TITLE' | translate:dynamic }}</pre>
<pre>{{ 'SUBTITLE' | translate:dynamic }}</pre>
<pre>{{ 'STATIC' | translate }}</pre>
This would spit out something like
Got there in the end.
in the .config
$translateProvider.useLoader('customLoader');
the customLoader...
angular.module('myapp').factory('customLoader', function ($q, TranslationService) {
return function (options) {
var deferred = $q.defer();
deferred.resolve(TranslationService.getLanguages().filter(function(lang){
return lang.key == options.key
})[0].values);
return deferred.promise;
};
});
and then a TranslationService to share the data
angular.module('myapp').factory('TranslationService', function () {
var languages = [];
return {
setLanguages: function (data) {
languages = data;
},
getLanguages: function () {
return languages;
}
}
});
Maybe check this:
http://www.ng-newsletter.com/posts/angular-translate.html
Under "Switching the language at runtime"
$translate.use(); // Returns the currently used language key
$translate.use('en'); // Sets the active language to `en`
app.controller('TranslateController', function($translate, $scope) {
$scope.changeLanguage = function (langKey) {
$translate.use(langKey);
};
});
this one works. storageService has local storage and after setting 'NG_TRANSLATE_LANG_KEY' in local storage. You can call it like below.
angular.module('myApp').run(['$rootScope', 'StorageService', function($rootScope, StorageService) {
$rootScope.currentLanguage = StorageService.local.get('NG_TRANSLATE_LANG_KEY') || 'en';
}]);
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1" ng-controller="TranslateController" ng-init="changeLanguage(currentLanguage)">
<li role="presentation"><a role="menuitem" tabindex="-1" href="javascript:;" ng-click="changeLanguage('tr')">TR</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="javascript:;" ng-click="changeLanguage('en')">EN</a></li>
</ul>
I think the best way to manage dynamically loading is
in the resolve config router block like
resolve: {
translatePartialLoader: function loadPartialLoader($translate,$translatePartialLoader) {
$translatePartialLoader.addPart('home');
return $translate.refresh();
}
}

Resources