I've got some projects displayed in divs via ng-repeat.
Each div contains a link with the id of the project.
Basically I want to bind my project id on ng-click in order to update a factory. This will allow me to share the clicked project's id with another controller who will load the project details data only.
Here is my projects view:
<div ng-repeat="detail in projects.details">
<a ng-href="#!/project/project-details" ng-click="setId(detail.project_id)"><span></span></a>
</div>
Here is my factory:
app.factory('getGoodIdProjectDetails', function (){
var savedId = 1; //Default à 1
return {
getId : function () {
return savedId;
},
setId:function(idGet){
savedId = idGet;
return savedId;
}
}
});
Here are my controllers:
function ProjectCtrl($scope, $http, $timeout, getGoodIdProjectDetails) {
$scope.setId = function (idGet) {
$scope.idProjectDetails = getGoodIdProjectDetails.setId(idGet);
};
}
function ProjectDetailsCtrl($scope, $http, $timeout, getGoodIdProjectDetails) {
$scope.idProjectDetails = getGoodIdProjectDetails.getId();
}
In my view the console is displaying an error like I can't bind ng-click this way, but when I inspect the view it's sorting me the good thing, like ng-click="setId(8)"
I want the factory to update with the good id on click. Then I want to access this id in projectDetailsCtrl in order to load the project.
|| EDIT || : I changed the ng-click, that works fine, everything's good. Thx all
try this:
<div ng-repeat="detail in projects.details">
<a ng-href="#!/project/project-details" ng-click="setId(detail.project_id)"><span>Voir le projet ></span></a>
</div>
you don't need to use binding expression {{}} to pass values to functions
Related
I've been teaching myself how to use the as statement of Angularjs's controller, but struggling to make controllers communicate with others, using the as syntax.
<script type="text/javascript">
angular.module('angularApp', [])
.factory('MessageService', function(){
var message = {
addedItem: "initialMessge"
};
return {
returnMessage: message//This is supposed to be the "var message" defined above
};
})
.controller('DiaplayingProductController', function(MessageService){
var instance = this;
this.data = {
message: MessageService.returnMessage.addedItem
};
})
.controller('ProductController', function($scope, $http, MessageService) {
var instance = this;
this.data = {
message: MessageService.message,
//There are other stuff here
};
this.addItem = function(productName) {
$http({
//other tasks
}).then(function addSucces(response) {
instance.data.message.addedItem = productName;
});
};
});
<span ng-controller="DiaplayingProductController as dpc" ng-bind="dpc.data.message"></span>
<div ng-controller="ProductController as pc">
#foreach ($products as $index => $product)
<div class="product">
<button ng-click="pc.addItem({{$product->name}})>
Add it to Cart
</button>
</div>
#endforeach
</div>
I use Laravel, so {{$product->name}} and #foreach are Laravel's expression.
In a nutshell,
There are one <span> and multiple <button>s, based on the result of #foreach (Again, I use Laravel, so this is basically the same thing as php's foreach)
When one of the <button> is pressed, the content of <span> is supposed to be updated.
The event is triggered in ProductController, which is supposed to update message of DiaplayingProductController, via MessageService.
The message is not going to be sent to the span tag.
This question may be silly. However, there are not many information resources out there which deal with this as statements, so I'd like to ask some advice here. Thank you in advance!
What's this #foreach?
There's a coma in your attributes. Shouldn't be there.
The expression in your ng-click has a missing parenthesis. Also, it should be an expression, therefore the {{}} have nothing to do here.
The data object are not shared between the controllers. You should:
use directives and pass the data using attributes ('=').
set the data in the $scope, which is not as good a solution
use a service as an intermediary (each controller can set/get the value
from that service)
I am new to Angular and need your help on an issue with the ng-repeat of my app.
Issue:
I have an html page (event.html) and in the corresponding controller of the file, I make a request to a firebase collection and update an array ($scope.events). The issue is that the data from firebase takes a few seconds to load and by the time data arrives to $scope.events, ng-repeat has already been executed and it displays an empty screen. The items are displayed correctly the moment I hit on a button in the HTML page (event.html).
Sequence of events:
I have a login page (login.html) where I enter a user name and phone number and I click on the register button. I've configured this click on the register button to go to the new state (event.html).
Here is the controller code for login.html:
$scope.register = function (user) {
$scope.user = user.name;
$scope.phonenumber = user.phonenumber;
var myuser = users.child($scope.user);
myuser.set({
phone : $scope.phonenumber,
Eventid : " ",
name : $scope.user
})
var userid = myuser.key();
console.log('id is ' +userid);
$state.go('event');
}
The controller of event.html (the state: event) has the following code:
var ref = new Firebase("https://glowing-torch-9862.firebaseio.com/Users/Anson/Eventid/");
var eventref = new Firebase("https://glowing-torch-9862.firebaseio.com/Events");
var myevent = " ";
$scope.events = [];
$scope.displayEvent = function (Eventid) {
UserData.eventDescription(Eventid)
//UserData.getDesc()
$state.go('myevents');
//console.log(Eventid);
};
function listEvent(myevents) {
$scope.events.push(myevents);
console.log("pushed to array");
console.log($scope.events);
};
function updateEvents(myevents) {
EventService.getEvent(myevents);
//console.log("success");
};
ref.once('value', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
$scope.id = childSnapshot.val();
angular.forEach($scope.id, function(key) {
eventref.orderByChild("Eventid").equalTo(key).on("child_added", function(snapshot) {
myevents = snapshot.val();
console.log(myevents) // testing 26 Feb
listEvent(myevents);
updateEvents(myevents);
});
});
});
});
$scope.createEvent = function () {
$state.go('list');
}
event.html contains the following code:
<ion-view view-title="Events">
<ion-nav-buttons side="primary">
<button class="button" ng-click="createEvent()">Create Event</button>
<button class="button" ng-click="showEvent()">Show Event</button>
</ion-nav-buttons>
<ion-content class="has-header padding">
<div class="list">
<ion-item align="center" >
<button class= "button button-block button-light" ng-repeat="event in events" ng-click="displayEvent(event.Eventid)"/>
{{event.Description}}
</ion-item>
</div>
</ion-content>
</ion-view>
The button showEvent is a dummy button that I added to the HTML file to test ng-repeat. I can see in the console that the data takes about 2 secs to download from firebase and if I click on the 'Show Events' button after the data is loaded, ng-repeat works as expected. It appears to me that when ng-repeat operates on the array $scope.events, the data is not retrieved from firebase and hence its empty and therefore, it does not have any data to render to the HTML file. ng-repeat works as expected when I click the dummy button ('Show Event') because a digest cycle is triggerred on that click. My apologies for this lengthy post and would be really thankful if any of you could give me a direction to overcome this issue. I've been hunting in the internet and in stackoverflow and came across a number of blogs&threads which gives me an idea of what the issue is but I am not able to make my code work.
Once you update your events array call $scope.$apply(); or execute the code that changes the events array as a callback of the $scope.$apply function
$scope.$apply(function(){
$scope.events.push(<enter_your_new_events_name>);
})
If you are working outside of controller scope, like in services, directive, or any external JS. You will need to trigger digest cycle after change in data.
You can trigger digest cycle by
$scope.$digest(); or using $scope.$apply();
I hope it will be help you.
thanks
In your case you have to delay the binding time. Use $timeout function or ng-options with debounce property in your view.
you have to set a rough time taken to get the data from the rest API call. By using any one of the methods below will resolve your issue.
Method 1:
var myapp = angular.module("myapp", []);
myapp.controller("DIController", function($scope, $timeout){
$scope.callAtTimeout = function() {
console.log("$scope.callAtTimeout - Timeout occurred");
}
$timeout( function(){ $scope.callAtTimeout(); }, 3000);
});
Method 2:
// in your view
<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ debounce: 1000 }" />
Here is the plunkr i have created.
Basically i am facing 2 issues with this piece of code -
I need help loading months in the drop down and
When month is changed in the dropdown from headerController, the sales for that month is displayed in detailController. I am trying to create a dependency between multiple controllers using a service.
I will appreciate any help fixing these 2 issues.
You can use $broadcast service for event purposes. Following is the link which explains the use of $broadcast and communicating between two controllers.
enter code herehttp://plnkr.co/edit/d98mOuVvFMr1YtgRr9hq?p=preview
You could simply achieve this by using $broadcast from one controller in $rootScope and listen that event in $scope using $on. Though I would suggest you to use service that will share data among to controller. Using dot rule will reduce your code. Take a look at below optimized code. Also you could replace your select with ng-repeat with ng-option to save object on select.
Markup
<div data-ng-controller="headerController">
<h3>Select Month</h3>
<select id="month" ng-model="sales.selectedMonth"
ng-options="month.monthId for month in sales.monthlySales">
</select>
</div>
<div data-ng-controller="detailsController">
<h3>Sales for Month</h3>
<div ng-bind="sales.selectedMonth"></div>
</div>
Code
app.service('valuesService', [function() {
var factory = {};
factory.sales = {}
factory.sales.salesForMonthId = 10;
factory.sales.months = [1, 2];
factory.sales.monthlySales = [{monthId: 1,sales: 10}, {monthId: 2,sales: 20}];
factory.sales.selectedMonth = factory.sales.monthlySales[0];
return factory;
}]);
app.controller('headerController', ['$scope', 'valuesService',
function($scope, valuesService) {
$scope.sales = {};
getData();
function getData() {
$scope.sales = valuesService.sales;
}
}
]);
app.controller('detailsController', ['$scope', 'valuesService',
function($scope, valuesService) {
$scope.sales = {};
getData();
function getData() {
$scope.sales = valuesService.sales;
}
}
]);
Demo Plunkr
I can see the months are already loading fine.
For proper data binding to work across service and controller, you would need to bind one level above the actual data, resulting a dot in your expression. This is because javascript doesn't pass by reference for primitive type.
In service:
factory.data = {
salesForMonthId: 0
}
In controller:
app.controller('detailsController', ['$scope', 'valuesService',
function ($scope, valuesService) {
$scope.values = valuesService.data;
}
]);
In template:
<div>{{values.salesForMonthId}}</div>
Plunker
I'm new to angular, trying to bind an an element's content into the controller's Scope to be able to use it within another function:
here is the scenario am working around:
I want the content of the <span> element {{y.facetName}} in
<span ng-model="columnFacetname">{{y.facetName}}</span>
to be sent to the controller an be put in the object $scope.columnFacetname in the controller
Here is a snippet of what I'm working on:
<div ng-repeat="y in x.facetArr|limitTo: limit track by $index ">
<div class="list_items panel-body ">
<button class="ButtonforAccordion" ng-click="ListClicktnColumnFilterfunc(); onServerSideButtonItemsRequested(ListClicktnColumnFilter, myOrderBy)">
<span>{{$index+1}}</span>
<span ng-model="columnFacetname">{{y.facetName}}</span>
<span>{{y.facetValue}}</span>
</button>
</div>
</div>
angular.module('mainModule').controller('MainCtrl', function($scope, $http) {
$scope.columnFacetname = "";
$scope.ListClicktnColumnFilter = "";
$scope.ListClicktnColumnFilterfunc = function() {
$scope.ListClicktnColumnFilter = "\":\'" + $scope.columnFacetname + "\'";
};
}
the problem is that the $scope.ListClicktnColumnFilter doesn't show the $scope.columnFacetname within it, meaning that the $scope.columnFacetname is not well-binded.
In your ng-click instead of calling two different function
ng-click="ListClicktnColumnFilterfunc(); onServerSideButtonItemsRequested(ListClicktnColumnFilter, myOrderBy)"
you can declare like this
ng-click="columnFacetname = y.facetName; onServerSideButtonItemsRequested(columnFacetname , myOrderBy)"
You are trying to pass that model to another function by assigning it to ListClicktnColumnFilter in your controller
By doing in this way, you can achieve the same thing.
I have done one plunker with sample array,
http://embed.plnkr.co/YIwRLWXEOeK8NmYmT6VK/preview
Hope this helps!
Nothing in my {{}} are showing in my html file. Can someone please tell me what I am doing wrong. I have no errors in my console.
"GOT DATA" will print in my console, but not show in my file.
The is my html code
<div class="announcements" ng-controller="onBusinessAnnouncementCtrl as announcements">
{{announcements.latest}}
</div>
This is my js code pulling from the server
app.controller('onBusinessAnnouncementCtrl', function($scope, $http) {
$http.get('http://localhost:3000/latest')
.success(function(responses) {
//$scope.latest = responses;
$scope.latest = "GOT DATA";
console.log($scope.latest);
});
});
Because you use the controller as syntac you should apply the variables in your controller to this instead of $scope.
See the same problem in AngularJS Ng-repeat is not working as expected where a repeater was used
below the answer on the previous question:
In your repeater you're looping over announcements.announcements in your controller you set $scope.announcements = response.
Either you change the repeater in ng-repeat="eachAnnouncement in announcements" or change your scope variable to: $scope.announcements = {announcements : response}
Figured it out! For reference:
There is nothing showing in my HTML because there is no value assigned to the controller. To assign "latest" to my controller I have to do this:
app.controller('onBusinessAnnouncementCtrl', function($scope, $http) {
$http.get('http://localhost:3000/latest')
var this = this;
.success(function(responses) {
this.latest = responses;
});
});
<div class="announcements" ng-controller="onBusinessAnnouncementCtrl as announcements">{{announcements.latest}}</div>