I have a bit of an interesting problem I am trying to currently figure out using angular.
I have 1 json object I need to use split between 2 controllers, I want to be able to change (save new items and delete json) the json in each controller separately. So when I modify something in one controller it just saves that part of the json - not the whole thing.
I will explain this as clearly as I can -
I have a factory that sends the json to both controllers, here's what it looks like(fake json data for now)
.factory("UserService", function($http) {
var LevelsHere = $http.get("/assets/images/generated.json")
.success(function(data){
return data;
});
return {
all: function() {
return LevelsHere;
}
};
})
Each controller then lists it as a dependancy then calls it like so -
UserService.all().then(function(data){
$scope.listTable = data.data;
});
This works great, and the 2way data binding is awesome in this case because if i change something in 1 controller, it changes immediately in the other. My real problem with this is I want to be able to save the content changed in the json in each controller individually.
So, the Json has a parent (name) and 2 children. Each controller has access to the parent and 1 of the children so for example. controller 1 has parent and child 1, and controller 2 has parent and child 2. When I want to click my save function - for example in controller 1 I want to save the json to the backend to overwrite the old stuff but only from the controller I am choosing to save. So Even if i made changes in controller 2, when I save 1, i Just want it to send parent(it's index) and child 1 to overwrite.
I think the problem may root from the fact that I am fully binding the data in each controller to all the the json maybe? Currently I am just trying to send the $scope.listTable back, and it's registering all the changes (between both sections).
Apologies if I rambled on here - I am trying to be as clear as possible. Thanks for taking the time to read!
EDIT I was thinking - and I don't know if this is possible so bear with me - Can it be designated that the json i bring into listTable only binds to what it needs. So for example - controller 1 only binded to all the parent and child 1 (and not child 2). Is this possible?
EDIT 2 Following up on the previous edit - I think I boiled down the question to - can I only save certain parts of the json instead of the whole object. I cannot have it save both child 1 and 2 at the same time because it might overwrite things that are not meant to be saved at that time. so it's either - can I just use the selected pieces of json, or can I just save the selected pieces of json. thanks again for reading!
Related
I am relatively new to Meteor, and I'm trying to create a web store for my sister-in-law that takes data from her existing Etsy store and puts a custom skin on it. I've defined all of my Meteor.methods to retrieve the data, and I've proofed the data with a series of console.log statements... So, the data is there, but it won't render on the screen. Here is an example of some of the code on the server side:
Meteor.methods({
...
'getShopSections': function() {
this.unblock();
var URL = baseURL + "/sections?api_key="+apiKey;
var response = Meteor.http.get(URL).data.results;
return response;
}
...
});
This method returns an array of Object. A sample bit of JSON string from one of the returned Objects from the array:
{
active_listing_count: 20,
rank: 2,
shop_section_id: 1******0,
title: "Example Title",
user_id: 2******7
}
After fetching this data without a hitch, I was ready to make the call from the client side, and I tried and failed in several different ways before a Google search landed me at this tutorial here: https://dzone.com/articles/integrating-external-apis-your
On the client side, I have a nav.js file with the following bit of code, adapted from the above tutorial:
Template.nav.rendered = function() {
Meteor.call('getShopSections', function(err, res) {
Session.set('sections', res);
return res;
});
};
Template.nav.helpers({
category: function() {
var sections = Session.get('sections');
return sections;
}
});
And a sample call from inside my nav.html template...
<ul>
{{#each category}}
<li>{{category.title}}</li>
{{/each}}
</ul>
So, there's a few things going on here that I'm unsure of. First and foremost, the DOM is not rendering any of the category.title String despite showing the appropriate number of li placeholders. Secondly, before I followed the above tutorial, I didn't define a Session variable. Considering that the list of shop categories should remain static once the template is loaded, I didn't think it was necessary from what I understand about Session variables... but for some reason this was the difference between the template displaying a single empty <li> tag versus a number of empty <li>'s equal to category.length --- so, even though I can't comprehend why the Session variable is needed in this instance, it did bring me one perceived step closer to my goal... I have tried a number of console.log statements on the client side, and I am 100% sure the data is defined and available, but when I check the source code in my Developer Tools window, the DOM just shows a number of empty li brackets.
Can any Meteor gurus explain why 1) the DOM is not rendering any of the titles, and 2) if the Session variable indeed necessary? Please let me know if more information is needed, and I'll be very happy to provide it. Thanks!
You set the data context when you use #each, so simply use:
<li>{{title}}</li>
If a Session is the right type of reactive variable to use here or not is hard to determine without knowing what you are doing but my rough guess is that a Mini Mongo collection may be better suited for what it appears you are doing.
To get you started on deciding the correct type of reactive variable to use for this head over to the full Meteor documentation and investigate: collections, sessions, and reactive vars.
Edit: To step back and clarify a bit, a Template helper is called a reactive computation. Reactive computations inside of helpers will only execute if they are used in their respective templates AND if you use a reactive variable inside of the computation. There are multiple types of reactive variable, each with their own attributes. Your code likely didn't work at all before you used Session because you were not using a reactive variable.
I have a MVC .NET application with AngularJS. In my route provider I use the controllers of mvc for retreiving the views as follows:
.when('/Units', {
templateUrl: 'Unit/Units'
})
.when('/UnitsDetail', {
templateUrl: 'Unit/UnitsDetail'
})
And my .NET UnitController has the following methods:
[Authorize]
public ActionResult Units()
{
return View();
}
[Authorize]
public ActionResult UnitsDetail()
{
ViewBag.reference = Guid.NewGuid().ToString().Substring(0, 6);
return View();
}
For the UnitsDetail view I need a reference that is generated in the UnitsDetail() method.
The problem comes when I go from Units to UnitsDetail several times. The first time the UnitsDetail() method is called and thus, the reference is generated but if I go back to Units and access again UnitsDetail the method is not called and the reference is the same. I need to generate one reference each time.
I know I could generate it using JS in the client or make an AJAX request from Angular to the server but what I really want to know is how to make Angular call the method UnitsDetail() every time I go to "#/UnitsDetail".
Thanks!
By default angular will cache all views in its template cache.
This is by design.
Angular expects the view to be just static HTML with the dynamic part marked using the {{ dynamicScopeVariable }} code. Angular will use scope objects to replaces the dynamic bit . But the static part will be shown from the cache.
The first time you execute the view , the view is cached.
You have 2 options here. Actually just one which is good from the Design point of you #2.
Option #1
Disable template caching in Angular as shown here
https://stackoverflow.com/a/27432167/2794980
This means that angular will call the HTML ACTION every time it needs the view.
This is not the best way to use angualar but it will work. You should also consider the performance side .. By far the most time consuming call on a ASP.NET MVC applications are Actions calls. This method means that while you are using a client side MVC framework , you are not utilizing one of its important benifits.
Options #2
Use a angualar service to get the GUID from back end . i.e. the code below.
ViewBag.reference = Guid.NewGuid().ToString().Substring(0, 6);
Preferably use a WebAPI if u can ( your request will be small ). The use angular to replace the GUID in ur VIEW.
It is not clear from the question why you need the GUID and if you could do with generating a random unique number using Javascript . If that is possible , it might be the best solution . But based on the info in the question you could use either of option 1 or 2.
Edit : Didn't realize that you have already tried option 2 , in that case Option 1 it is.
Edit 2 : If you want to remove a single element from the cache , you can do
$templateCache.remove("<Element Name>");
or you could use the
$cacheFactory.remove("Name")
Read more about cache factory here :
https://docs.angularjs.org/api/ng/service/$cacheFactory
The name is generally the page name , you can look at the template cache or cache factory object in debugger console to find the exact name.
I am stuck in one scenario where i have to pass data from one controller to another controller.
My app works like this:
View 1 -> gets some users from json array and displays in a table.
When i click add user in View 1, i get redirected to view 2.
View 2 -> has 2 input fields and a button (to add a new user).
When i redirect to view 1, i want the new user to get appended but this is not working.
To make it easy, i have demoed this here - http://plnkr.co/edit/yz6mpplZGh4q5bPDO2bc?p=preview
Any help is much appreciated.
You are always overwriting the 'users' content on entry of the list controller.
Change your controller to
...
controller('UserController', function($scope,UserService){
if (!$scope.users)
{
UserService.getUsers().then(function(data){
$scope.users = data;
})
}
...
And bring back your 'correct'
$scope.users.push($scope.user)
in your addUserController.
View2 directive needs to define that it requires View1. This will tell Angular to pass the controller for View1 as an argument to View2's controller.
You can then call a method addUser(..) on that controller.
https://docs.angularjs.org/guide/directive#creating-directives-that-communicate
I have two controllers FundsController and FundRequestContoller. FundRequestController is used to show fund request received to an user. And FundsController contains a form which has an option to select on of my friend and amount that a user wish to send to his friend.
And, when ever a user accept a particular fund request by a friend, a state transition should happen to navigate the user from FundRequestController view to FundsController view where the friend id and amount to requested be pre-populated.
I would like to create a json object and share this object with FundsController so that when it is initialized the friend id and amount can be pre-populated using json object.
I dont want to use query params since too much information will be displayed to user in the browser url.
How can I share a json objects from one controller to another controller that can be used to initialize the other controller??
Use factory to create your service which holds the shared data. This service is then injected into both of your controllers as a dependency.
app.factory("sharedDataService", function() {
return {
yourData: "whatever"
};
});
see this :
great SO answer and example here: https://stackoverflow.com/a/13482919/36546
Video here: https://egghead.io/lessons/angularjs-sharing-data-between-controllers
Best approach is to make factory file as common to both controllers .
More Info
http://plnkr.co/edit/UA28cXfF0I8r3M54DyYa?p=preview
Another simple method is that make one function as global and share data
Controller 1
$scope.shareData( data ) = function(){
$scope.sampleFunction( data) ;
};
Controller 2
$rootScope.sampleFunction( data ) = function(){
console.log(data);
// your logic
};
More Info
In the project I am working on I have a lot of serial true/false data that needs to be displayed in different ways. I have been working on a directive that will allow me to pass in the model, the table header, and heres the tricky part, number of columns.
<serial-checkbox-table title="Title" columns="2" ng-model="items"></serial-checkbox-table>
I cant seem to get the columns parameter to be respected. I built this thing at one point where the html was generated in the link phase but I was having a hard time updating the model that was passed into the directive.
heres a jsfiddle of the current state of the directive.
http://jsfiddle.net/peledies/2tVAe/
Anyone have any ideas?
What you need is a $scope.$watch on the model variable.
Here is your old cold:
var model = $scope.$eval($attrs.ngModel);
...
// compile and write to dom
Needs to updated to
$scope.$watch($attrs.ngModel,function(newVal,oldVal) {
//var model = $scope.$eval($attrs.ngModel);
// can just take model value from watch function result
var model = newVal;
...
// compile and write to dom
});
And here is your jsfiddle updated with this logic: http://jsfiddle.net/callado4/2tVAe/7/