angularJS -Change in variable visible between html links - angularjs

I have this code:
<li ng-repeat="objekt in driversList" class="mix {{objekt.Objekt.Type}}">
<a href="objekttest.html" data-ajax="false"
ng-click="objekt.Objekt.Active='yes'">
<img ng-src="../images/thumbs/{{objekt.Objekt.Thumb}}.jpg"
style="margin-right:0;" >
<span id="list">{{objekt.Objekt.Name}}{{objekt.Objekt.Active}}</span>
<span id="listmala">{{objekt.Objekt.Type}}</span>
</a>
</li>
objekt.Objekt.Active changes when I click the corresponding <li> tag.
However, on the other HTML link, I have:
<div ng-repeat="objekt in driversList">
{{objekt.Objekt.Name}} {{objekt.Objekt.Active}}
</div>
This time, objekt.Objekt.Active keeps the default value (i.e. 'no').
Is it possible to change a scope variable permanently so that it is changed on some other HTML element?
Here's my controller code:
angular.module('aki', [
'aki.controllers'
]);
angular.module('aki.controllers', []).
controller('akicontroller', function($scope,$rootScope) {
//$scope.toggle = function(){
//$scope.driversList.
//}
$rootScope.active='da';
$scope.driversList = [
{
Objekt: {
Name: 'Saint & Sinner',
Type: 'nightclub',
Thumb: 'Sinner',
Active:'no'
}
},
{
Objekt: {
Name: 'Corner Cafe',
Type: 'cafe',
Thumb: 'corner caffe',
Active:'no'
}
},...
...
EDIT: I'm making multipage application without Ajax

Not without using some form of backend or storage.
Looking at your code, you appear to have hard coded the driversList into the .js file. You're also navigating to a new page, it appears. AngularJS doesn't edit that JS file, so that's not going to persist.
You'll need to either have a backend service that stores the state (in memory or database) via http request, have AngularJS not actually change location (putting all of this on the same page, and show/hiding it as you interact), or use something like HTMLStorage to save/load the data.
You can also use something like AngularJS's Firebase backend to serve as persistence for the data - https://www.firebase.com/quickstart/angularjs.html has a quick start guide.

Related

Cannot bind response object from POST to my view

I've been trying to solve this for hours, and have tried to find a working solution on stack overflow and other sites, but none worked so far.
The Issue
I am building a travelogue web app that allows users to log and view their journeys (e.g. a road trip). At the moment I am implementing the feature that lets users view a particular journey in a separate view which they have selected from a list of journeys. I pass down the id of the selected journey and retrieve an Object from MongoDB. I implemented this using POST. It works in that the _id of the selected journey is passed in the request, then used to identify the document with Model.findById - then the response yields the data. The data is bound to $scope.selection.
But while $scope.selection contains the data (when logged to console), I cannot seem to bind it to the view (called view_journey). Meaning, whenever I want to access, e.g. selection.name in my view_journey.html, the expression or ng-bind is left empty.
app.js
$scope.viewJourneybyId = function(id) {
var selectOne = { _id : id };
$http.post('http://localhost:8080/view_journey', selectOne).
success(function(data) {
$scope.selection = data;
$scope.$apply();
console.log("POST found the right Journey");
console.log($scope.selection);
}).error(function(data) {
console.error("POST encountered an error");
})
}
server.js
app.post("/view_journey", function(request, response, next) {
Journeys.findById(request.body._id, function(error, selection) {
if (error)
response.send(error)
response.json({ message: 'Journey found!', selection });
});
});
index.html
<tr ng-repeat="journey in journeys">
<td>
<a href="#/view_journey" ng-click="viewJourneybyId(journey._id)">
{{journey.name}}</a>
</td>
<td>...</td>
</tr>
view_journey.html
<div class="panel panel-default">
<div class="panel-heading">
<h2 ng-bind="selection.name"></h2>
<!-- For Debugging -->
ID <span ng-bind="selection._id">
</div>
<div class="panel-body">
<table class=table>
<caption>{{selection.desc}}</caption>
...
</table>
</div>
</div>
Feedback
This is my first question on stack overflow, so please also tell me if I phrased my question in a way that could be misunderstood, and whether or not I should supply more details, e.g. console output. Thank you ;)
After fiddling with your code I can confirm that when triggering the route you are getting a new instance of the controller that has a new, clean scope. This is the expected behavior with AngularJS.
You can verify this by adding a simple log message as the first line of your controller:
console.log($scope.selected);
You will notice that it always logs out "undefined" because the variable has never been set (within viewJourneyById). If you leave that logging in and test the code you will see the logging fire in viewJourneyById but then immediately the "undefined" as it loads the view_journey.html template into ng-view and creates the new instance of mainCtrl. The presence of the "undefined" after the new view loads shows that the controller function is being executed again on the route change.
There are a couple of ways to address this. First you could create a factory or service, inject it into your controller, and have it store the data for you. That is actually one of the reasons they exist, to share data between controllers.
Factory:
travelogueApp.factory('myFactory',function() {
return {
selected: null,
journeys: []
};
});
Controller:
travelogueApp.controller('mainCtrl', ['$scope','$http','$location','myFactory', function ($scope, $http, $location, myFactory) {
// put it into the scope so the template can see it.
$scope.factory = myFactory;
// do other stuff
$scope.viewJourneybyId = function(id) {
var selectOne = { _id : id };
$http.post('http://localhost:8080/view_journey', selectOne)
.success(function(data) {
$scope.factory.selection = data;
console.log("POST found the right Journey");
console.log($scope.factory.selection);
})
.error(function(data) {
console.error("POST encountered an error");
})
}
}]); // end controller
Template:
<div class="panel panel-default">
<div class="panel-heading">
<h2>{{factory.selection.name}}</h2>
</div>
<div class="panel-body">
<table class=table>
<caption>{{factory.selection.desc}}</caption>
...
</table>
</div>
</div>
More or less something like that. Another way to do it would be to construct the link with the journey id as part of the query string and then in the controller check for the presence of the journey id and if you find one, look up the journey. This would be a case of firing the route, loading a new instance of the controller and then loading the data once you're on the view_journey page. You can search for query string parameters in the controller like this:
var journey_id = $location.search().id;
Either way works. The factory/service method allows you to minimize web service calls over time by storing some data. However, then you have to start considering data management so you don't have stale data in your app. The query string way would be your quickest way to solve the problem but means that every route transition is going to be waiting a web service call, even if you are just going back and forth between the same two pages.

AngularGrid doesn't load when refresh page

I'm using this AngularGrid system and everything is working so far, except when i refresh the page.
In the doc there is an orientation on how to solve this:
To get the reference of instance you need to define angular-grid-id on the element which you can get back by injecting angularGridInstance to any controller or directive. Using your id you can refresh your layout ex : angularGridInstance.gallery.refresh();
And this is what I did:
html
<ul class="dynamic-grid" angular-grid="pics" angular-grid-id="mypics" grid-width="300" gutter-size="10" refresh-on-img-load="false" >
<li data-ng-repeat="port in Portfolio" class="grid" data-ng-clock>
<img src="{{port.img[0]}}" class="grid-img" />
</li>
</ul>
app.js
.directive('myPortfolio', ['mainFactory','angularGridInstance', function (mainFactory,angularGridInstance) {
return {
restrict: "A",
link: function($scope) {
mainFactory.getPortfolio().then(function(data) {
$scope.refresh = function(){
angularGridInstance.mypics.refresh();
}
$scope.pagedPortfolio = data.data;
})
}
}
}])
But if I refresh the page, it still doesn't work. There is some boxes but without image loaded and it's not inside the grid system. Also, I have no errors in my console. When this happens, I can only see the images again if I change to another page and then go back to my portfolio page.
Any ideas on how to solve this?
I think you don't need angularGridInstance and refresh function here. Just change
refresh-on-img-load="false"
to
refresh-on-img-load="true"
in your view.

How to fix my partial in order it updates when model updates?

In my HTML, I have a series of tab, that changes the content of the partial as follows:
<ul class="nav nav-tabs">
<li
ng-repeat="project in projects"
ng-class="currentProject==$index?'active':''">
<a ng-click="setProject($index)" >{{project.title}}</a>
</li>
</ul>
<h2>{{project.title}}</h2>
<ul class="nav nav-tabs">
<li ng-class="getPage()=='/project/status' ?'active':''"><a ng-href="#/project/status" >Résumé</a></li>
<li ng-class="getPage()=='/project/graphs/burndown' ?'active':''"><a ng-href="#/project/graphs/burndown" >Graphe RÀF</a></li>
<li ng-class="getPage()=='/project/details'?'active':''"><a ng-href="#/project/details" >Liste détails</a></li>
</ul>
<!-- partial content -->
<section id="partial" ng-view></section>
In my controller I have:
$scope.setProject = function(id) {
$scope.currentProject = id;
$scope.project = $scope.projects[id];
//$scope.$apply($scope.project);
}
The issue I face is that when I switch the current project by tapping on one of the first tabs, though {{}} are updated in the HTML, the partial itself is not updated.
I suspect I have to call $apply in some ways, but I'm confused: where and how?
As you can see in the controller method setProject() I ran some tests without success.
[UPDATE] The fiddle: http://jsfiddle.net/stephanedeluca/Zk2qa/21/
The problem with your example is that you're calling $scope.setProject(0) in your controller. All your templates use the same controller, and when you navigate to a new route, the controller runs again and resets the project to 0 (you can see this happening if you watch the console while you navigate around). Take out the $scope.setProject(0) and it should work. Realistically, each of your templates would probably have a separate controller, as would your top level navigation.
Update
Responding to your question below. I am still learning Angular myself and am by no means an expert, so take everything I say with a grain of salt.
A controller is basically the brain behind the view. It prepares the data, and handles the interface logic. The user interfaces with the view, and the view interfaces with the controller, with interfaces with the rest of the application.
In your case, you have three views that all use the same data. But they do different things (even if all they do differently is display the same data in different ways). Each view has a different purpose, and each should have a different brain/controller. Maybe one view has a sortable grid, and another view has a button for generating a pdf (and if they don't now, maybe they will next month). You don't want to be mixing all the logic for all the views together. It will become a mess and hard to work with.
There are a few ways to make your data available to your controllers. If your data is self-contained on the client (which it sounds like it is in your case), you could stuff it into a value or constant like this:
app.constant('projects', [
{ id: 0,
name: 'Proj1',
title: 'First project',
description: ['First project description']
},
{ id:0,
name: 'Proj2',
title: 'Second project',
description: ['Second project description']
}
]);
or even just assign it to the $rootScope. That might work fine, but it doesn't really feel right. And one day you may decide that you want to load your data from a remote server afterall. It probably makes more sense to put your data access into a service.
app.service('dataService', function(){
return{
getData: function(){
return [
{ id: 0,
name: 'Proj1',
title: 'First project',
description: ['First project description']
},
{ id:1,
name: 'Proj2',
title: 'Second project',
description: ['Second project description']
}
];
}
};
});
Here, the service returns a getData function which returns your list of projects. Right now, it just returns the hard-coded array of projects, but your could also put an $http call in there to pull the data from a server somewhere. If you decide to make that change some day, you won't have to change a bunch of code in your controllers, because all they have access to is getData and they don't care where the data comes from.
Your controllers also need to know which project is selected, so it makes sense to use a service for that as well. Here's my navService:
app.service('navService', function(){
selectedProject = {};
return {
getProject: function(){
return selectedProject;
},
setProject: function(project){
selectedProject = project;
}
};
});
It just keeps track of which project is selected, and provides getter and setter functions.
Here's a Fiddle.
Hope that all made sense. I would encourage anyone to correct me if anything I wrote is not correct.

how to get href by ng-click a <a> in angular?

let us say we have a
Click Here
in the angular based application.
$scope.myFunction= function(){
// how to get the href
$http.get(href).success(function(data) {
})
}
the requirement is to click the and do a ajax request and get the json data from the server. since I choose to work on the angular, I don't know how to it in angular, since I don't know how to get the href attribute from the element
Try:
Click Here
Js:
$scope.myFunction= function(href){
// how to get the href
$http.get(href).success(function(data) {
})
}
DEMO
I using angularjs 1.5 and $event.target.href didn't work in my app.
I had to do this:
<a ng-click="$event.preventDefault();vm.openToolTip($event);" href="J3606">position 36.06</a>
js
function openToolTip(event){
var href = event.currentTarget.attributes["href"].nodeValue;
alert(href);
}

How to reload / refresh model data from the server programmatically?

Background
I have the most basic "newbie" AngularJS question, forgive my ignorance: how do I refresh the model via code? I'm sure it's answered multiple times somewhere, but I simply couldn't
find it.
I've watched some great videos here http://egghead.io and went quickly over the tutorial, but still I feel I'm missing something very basic.
I found one relevant example here ($route.reload()) but I'm not sure I understand how to use it in the example below
Here is the setup
controllers.js
function PersonListCtrl($scope, $http) {
$http.get('/persons').success(function(data) {
$scope.persons = data;
});
}
index.html
...
<div>
<ul ng-controller="PersonListCtrl">
<li ng-repeat="person in persons">
Name: {{person.name}}, Age {{person.age}}
</li>
</ul>
</div>
...
This all works amazingly well, each time the page is reloaded I see the list of people as expected
The questions
Let's say I want to implement a refresh button, how do I tell the model to reload programmatically?
How can I access the model? it seems Angular is magically instantiating an instance of my controller, but how do I get my hands on it?
EDIT added a third question, same as #1 but how can it be done purely via JavaScript?
I'm sure I'm missing something basic, but after spending an hour trying to figure it out, I think it deserves a question. Please let me know if it's duplicate and I'll close + link to it.
You're half way there on your own. To implement a refresh, you'd just wrap what you already have in a function on the scope:
function PersonListCtrl($scope, $http) {
$scope.loadData = function () {
$http.get('/persons').success(function(data) {
$scope.persons = data;
});
};
//initial load
$scope.loadData();
}
then in your markup
<div ng-controller="PersonListCtrl">
<ul>
<li ng-repeat="person in persons">
Name: {{person.name}}, Age {{person.age}}
</li>
</ul>
<button ng-click="loadData()">Refresh</button>
</div>
As far as "accessing your model", all you'd need to do is access that $scope.persons array in your controller:
for example (just puedo code) in your controller:
$scope.addPerson = function() {
$scope.persons.push({ name: 'Test Monkey' });
};
Then you could use that in your view or whatever you'd want to do.
Before I show you how to reload / refresh model data from the server programmatically? I have to explain for you the concept of Data Binding. This is an extremely powerful concept that will truly revolutionize the way you develop. So may be you have to read about this concept from this link or this seconde link in order to unterstand how AngularjS work.
now I'll show you a sample example that exaplain how can you update your model from server.
HTML Code:
<div ng-controller="PersonListCtrl">
<ul>
<li ng-repeat="person in persons">
Name: {{person.name}}, Age {{person.age}}
</li>
</ul>
<button ng-click="updateData()">Refresh Data</button>
</div>
So our controller named: PersonListCtrl and our Model named: persons. go to your Controller js in order to develop the function named: updateData() that will be invoked when we are need to update and refresh our Model persons.
Javascript Code:
app.controller('adsController', function($log,$scope,...){
.....
$scope.updateData = function(){
$http.get('/persons').success(function(data) {
$scope.persons = data;// Update Model-- Line X
});
}
});
Now I explain for you how it work:
when user click on button Refresh Data, the server will call to function updateData() and inside this function we will invoke our web service by the function $http.get() and when we have the result from our ws we will affect it to our model (Line X).Dice that affects the results for our model, our View of this list will be changed with new Data.

Resources