Updating $Scope variable between two aspx web page - asp.net

I have a search page , once user clicks Search button it calls an angualrjs function, where I need to update some $scope variables and redirect to another page.
This is my service to share the object between controllers
var app = angular.module('MyApp', ['angular.filter', 'googlechart']);
app.factory('sharedService', function () {
var testObj = {
name:'User Name 1',
age: 25
};
var searchParameter = function (newObj) {
testObj = newObj;
};
var getParameter = function () {
return testObj;
};
return {
searchParameter: searchParameter,
getParameter: getParameter
};
});
Here is the Controller 1 : SearchController
app.controller('SearchController', function ($scope, $parse, $filter, $location, $window, sharedService) {
$scope.searchParameter = function (searchParameter) {
var testObj = {
name: 'UserName 2',
age: 35
};
sharedService.searchParameter(testObj);
$window.location.href = 'http://localhost:8080/UI/SearchResult.aspx';
}
});
And this is my controller 2 : ResultController
app.controller('ResultController', function ($scope, $parse, $filter, sharedService) {
$scope.getParameter = function () {
$scope.testParam = sharedService.getParameter();
}
});
testObj is a model.
It is redirecting to the result page, but the testObj value is not getting updated to UserName 2.
How can I get updated value in the controller 2?

This is not working because in your service, the object is declared as var. So even if you're updating from outside, it will not return the value.
Also apart from service, if your pages are like parent-child controller, you can share objects between controller. Let me know if service solution is not working, I can share solution for sharing objects between controllers.
The variable should be bound to the service. Something like below:
var app = angular.module('MyApp', ['angular.filter', 'googlechart']);
app.factory('sharedService', function () {
this.testObj = {
name:'User Name 1',
age: 25
};
var searchParameter = function (newObj) {
this.testObj = newObj;
};
var getParameter = function () {
return this.testObj;
};
return {
searchParameter: searchParameter,
getParameter: getParameter
};
});

Related

Get single item data by ID in angular JS

I have articles which i'm getting from my API. My API lists them correctly when i go to http://localhost:60367/api/article/ and gets the correct data correctly for a single item when i go to http://localhost:60367/api/article/1
Using angular, how get the data for one of these articles by it's id so that if i go to my angular app and click to http://localhost:60300/perspectives/1/ I get the data of that one item. ( fyi, When i go to the index http://localhost:60300/perspectives/ I get the data accordingly. )
Please assist, my app.js file is below:
var url = "http://localhost:60367/api/article";
var modules = ['ngRoute', 'ngSanitize'];
var App = angular.module("App", modules);
// Route providers
App.config(function ($routeProvider, $locationProvider) {
$routeProvider
// Get route for perspectives homepage
.when('/', {templateUrl: 'partials/articles-home.html',
controller: ArticleController})
// Get route for perspectives single page
.when("/:id/", {templateUrl: 'partials/articles-single.html',
controller: ArticleController})
.otherwise({ redirectTo : "/"})
// Use the HTML5 History API
$locationProvider.html5Mode({ enabled: true, requireBase: false});
});
// Controller
var ArticleController = function ($scope, $http, $log) {
// For onsuccess, also do console.log for $log property
var onSuccess = function (response) {$scope.articles = response.data;
$log.info(response);};
var onFailure = function (reason) {$scope.error =
reason;$log.info(reason);};
// Get all students and display them in index
var getAllArticles = function () {$http.get(url).then(onSuccess,
onFailure)};
getAllArticles();
// Get single student by Id
//
//
};
App.controller("ArticleController", ArticleController);
SOLUTION:
Ok this is how I solved it, I created a new controller for the single item and wrote it manually like this:
var SingleArticleController = function ($scope, $http, $routeParams) {
$http({
url: "http://localhost:60367/api/article/{id}",
params: { id: $routeParams.id },
method: "get"
})
.then(function (response) {
$scope.article = response.data;
});
};
You'll want to use $routeParams:
What I've outline here will allow you to use the same controller here as that's what you've show in your config. Often-times, you'd assign a separate controller in your route (something like ArticleController, ArticleListController.). If you do that, the same process applies, but you wouldn't need to check if you have an ID parameter.
In your Controller:
// Add $routeParams
.controller('ArticleController', function($scope, $routeParams) {
// Get the id
var id = $routeParams.id;
// Set url based on whether or not you have an ID
var fullUrl = id ? url + '/' + id : url;
var getAllArticles = function() {
$http.get(fullUrl).then(onSuccess,
onFailure)
};
})

Sharing data stored in angularjs

I'm trying to shared data between controller.
I'm calling data, then stored in AngularJS Factory variable.
My goal when stored the data was to make it accessible to any controller. But in application, every time i called the stored data from each controller, seems like i got a new instance of my factory instead of my factory that already contain the data.
Do you think i'm doing the wrong way when using factory or there was something i've been missed ?
Here it is
Factory Code:
var Credentials = ['abc'];
function load() {
var service = HeaderService.get("api/CredentialsAPI/get");
service.then(function (response) {
if (response.status == 200)
Credentials = response.data;
});
alert("inside:" + Credentials.length);
}
load();
return {
SubmitCredentials : function (obj) {
angular.forEach(obj, function (value) {
Credentials.push(value);
});
},
GetCredentials : function (name) {
var datax = {};
alert(Credentials.length)
angular.forEach(Credentials, function (value) {
if (value.Name == name) {
datax = value;
}
});
return datax;
}
}
Home Controller:
loadHome();
function loadHome() {
$scope.Credentials = CredentialsService.GetCredentials("Task");
}
AssignTask
$scope.showSubmitView = false;
//----------------------------------function--------------------------------------
$scope.Credentials[] = CredentialsService.GetCredentials("Task");
You're referencing a new array every time. That's why you're getting new data. You should be referencing the service instead, and have the service take care of the push() and get for you.
Factories and Services are singletons... Meaning they're only instantiated once. The pattern to share data is below:
Factory
app.factory('CredentialService',["$http", function($http) {
var credentials = [];
var submitCredentials = function(obj) {
angular.forEach(obj, function(value) {
credentials.push(value);
});
}
var getCredentials = function(name) {
var datax = {};
if(credentials.length === 0)
return datax;
angular.forEach(credentials, function(value) {
if(value.Name === name) {
datax = value;
break; //i think you meant to break; over here
}
});
return datax;
}
//return the service;
return {
getCredentials: getCredentials,
submitCredentials: submitCredentials
};
}]);
Controller
app.controller("Ctrl1", ["$scope", "CredentialService", function($scope, CredentialService) {
var credObj = CredentialService.getCredentials('blahblahblah');
var someNewCredObj = 'blahhhh';
CredentialService.submitCredentials(someNewCredObj);
}]);

How do I access the data context and the template instance in each case (event, helper, hook)?

My brain is hurting because of all the inconsistency. Please have a look at the code below and correct/complete it:
Template.Example.events({
'click #example': function(event, template) {
instance = template; // or = Template.instance();
instance_reactive_data_context = template.currentData(); // or = Template.currentData();
instance_nonreactive_data_context = ???
event_data_context = event.currentTarget;
});
Template.Example.helpers({
example: function() {
instance = Template.instance();
instance_reactive_data_context = this; // or = Template.currentData();
instance_nonreactive_data_context = ???
}
});
Template.Example.onCreated(function () {
instance = this;
instance_reactive_data_context = this.currentData();
instance_nonreactive_data_context = this.data;
});
Here's the answer, which even shows a bit more. It includes creating and accessing a reactive-var or reactive-dictionaries attached to the template. All this is extremely important to understand for Meteor developers:
Template.Example.onCreated(function () {
instance = this; // or = Template.instance();
// instance_reactive_data_context = no point in having a reactive data context since this function is only executed once
instance_nonreactive_data_context = this.data;
// now in order to attach a reactive variable to the template:
let varInitialValue = ...
instance.reactive_variable = new ReactiveVar(varInitialValue);
// and now let's attach two reactive dictionaries to the template:
let dictInitialValue_1 = { ... }
let dictInitialValue_2 = [ ... ]
instance.reactive_dictionaries = new ReactiveDict();
instance.reactive_dictionaries.set('attachedDict_1', dictInitialValue_1);
instance.reactive_dictionaries.set('attachedDict_2', dictInitialValue_2);
});
Template.Example.events({
'click #example': function(event, template) {
instance = template; // or = Template.instance();
instance_reactive_data_context = Template.currentData();
instance_nonreactive_data_context = template.data;
event_data_context = event.currentTarget;
// to access or modify the reactive-var attached to the template:
console.log(template.reactive_variable.get());
template.reactive_variable.set('new value');
// to access or modify one of the reactive-dictionaries attached to the template:
console.log(template.reactive_dictionaries.get('attachedDict_2'));
template.reactive_dictionaries.set('attachedDict_2', { newkey: 'new value', somearray: ['a', 'b'] });
});
Template.Example.helpers({
example: function() {
instance = Template.instance();
instance_reactive_data_context = this; // or = Template.currentData();
// instance_nonreactive_data_context = it can't be accessed as a non-reactive source. When you'll need something like this, most likely because the helper is running too many times, look into the [meteor-computed-field][1] package
// to access or modify the reactive-var attached to the template:
console.log(Template.instance().reactive_variable.get());
Template.instance().reactive_variable.set('new value');
// to access or modify one of the reactive-dictionaries attached to the template:
console.log(Template.instance().reactive_dictionaries.get('attachedDict_2'));
Template.instance().reactive_dictionaries.set('attachedDict_2', 'new value here');
// obviously since you declared instance on the first line, you'd actually use everywhere "instance." instead of "Template.instance()."
}
});

Pagination with meteor and iron router not re-rendering

I'm really struggling to understand what's going on here. I have a template
<template name="gallery">
<div>
123
</div>
{{#each art}}
{{name}}
{{/each}}
</template>
Then I have routes like this
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
return {
page: page,
};
},
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
return {
page: page,
};
},
});
});
Following this article I'm using template subscriptions like this
var G_PAGE_SIZE = 10;
Template.gallery.onCreated(function() {
var instance = this;
var route = Router.current();
instance.loaded = new ReactiveVar(0);
instance.autorun(function() {
var pageId = parseInt(route.params._page);
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
if (subscription.ready()) {
instance.loaded.set(1);
}
});
instance.art = function() {
return Art.find({});
};
});
Template.gallery.helpers({
art: function() {
return Template.instance().art();
},
});
It works but when I click one of the links changing the route the page doesn't re-render
So ... some other answer on here said that's because there's no reactive connection between data changing on the route through the router and the template.
So I tried use route.state which as a ReactiveDict (not sure where that came from). If it's part of iron:router or if it's part of reactive-var
Anyway I changed the code to
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
this.state.set('page', page); // <------------ADDED
return {
page: page,
};
},
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
this.state.set('page', page); // <------------ADDED
return {
page: page,
};
},
});
});
In the onCreated
Template.gallery.onCreated(function() {
var instance = this;
var route = Router.current();
instance.loaded = new ReactiveVar(0);
instance.autorun(function() {
var pageId = route.state.get('page'); // <--------- CHANGED
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
if (subscription.ready()) {
instance.loaded.set(1);
}
});
instance.art = function() {
return Art.find({});
};
});
Template.gallery.helpers({
art: function() {
return Template.instance().art();
},
});
That doesn't work either except sometimes. In the interest of debugging I added a console.log to the route
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
this.state.set('page', page);
console.log("/root"); // <------------ADDED
return {
page: page,
};
},
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
this.state.set('page', page);
console.log("/gallery/" + page); // <------------ADDED
return {
page: page,
};
},
});
});
Suddenly it starts working !???!#!? I remove the console.logs and it stops
I also tried adding actions without the console.logs
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
this.state.set('page', page);
return {
page: page,
};
},
action: function() { // <- added
var page = 1; // <- added
this.state.set('page', page); // <- added
this.render(); // <- added
}, // <- added
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
this.state.set('page', page);
return {
page: page,
};
},
action: function() { // <- added
var page = parseInt(this.params._page); // <- added
this.state.set('page', page); // <- added
this.render(); // <- added
}, // <- added
});
});
That doesn't work either.
update
So using Router.current().data().??? seems to make it work. It's now this
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
// <--- removed this.state() stuff
return {
page: page,
};
},
// <---- removed action stuff
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
// <--- removed this.state() stuff
return {
page: page,
};
},
// <---- removed action stuff
});
});
helper
Template.gallery.onCreated(function() {
var instance = this;
instance.loaded = new ReactiveVar(0);
instance.autorun(function() {
var route = Router.current(); // <----- Moved from 3 lines up
var pageId = route.data().page; // <--------- CHANGED
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
if (subscription.ready()) {
instance.loaded.set(1);
}
});
instance.art = function() {
return Art.find({});
};
});
Template.gallery.helpers({
art: function() {
return Template.instance().art();
},
});
No idea if this is now correct or if I'm just getting lucky like with the console.log editions
My guess is that your autorun function is not being re-run because you are not using any reactive variables. I'm not sure if Router.current() or Router.current().data() are reactive, but if they're not, then this explains the issue clearly for me. To test this, try putting some console logging in your autorun function.
Now, I would proposed some revisions that may work for you.
Routing code
Redirect to '/' URL to '/gallery/1' so you can re-use routing code
Router.route('/', function(){
this.redirect('/gallery/1');
});
Sending the page number in the data object to your template is important so that we can use this object in our autorun function
Router.route('/gallery/:_page', {
template: 'gallery',
data: function() {
return {
page: this.params._page,
};
}
});
Also, you don't need to use parseInt method unless you are trying to re-route or handle that exception in your routing code.
Gallery onCreated and helpers
There is a Template.subscriptionsReady helper provided by Meteor so you don't have to manually check if the subscription is loaded unless you really want it. Here's the Template.subscriptionsReady documentation
Here's a simplified version of your onCreated method using the template.data object which was built by the routing code above. Using the autorun wrapper is important so that it will re-run when template.data is changed by your router.
var G_PAGE_SIZE = 10;
Template.gallery.onCreated(function() {
var instance = this;
instance.autorun(function() {
// access the data object built by your route code
var pageId = instance.data.page;
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
});
});
Define access to your reactive data sources using the template.helpers method.
Template.gallery.helpers({
art: function() {
return Art.find({});
}
});
Note: Not necessary to define your helper in the onCreated and template.helpers

Multiple Data Contexts in router - Meteor

I'm building a meteor app and on one route I'm adding multiple data context like so -
this.route('orgPage', {
path: '/org/:title',
data: {
orgs: function () {Orgs.findOne(this.params._id)},
projects: function() {Meteor.subscribe('projects', this.params._id)}
}
The only problem is that when I try to access this data in my templates js file, I can't access the _id or any of the attributes of orgs.
I've tried several approaches, but it always returns undefined. If I use a single data context, it works perfectly. Here is the function that doesn't function properly -
Template.orgPage.events({
'click #newProject': function(e) {
$('#npModal').modal();
},
'submit #npModal form': function(e, template) {
e.preventDefault();
if(!$(e.target).find('[name=newTitle]').val()) {
var projectTitle = 'Untitled'
} else {
var projectTitle = $(e.target).find('[name=newTitle]').val()
}
var theid = this._id;
var newProject = {
title: projectTitle,
organization: theid
}
Meteor.call('project', newProject, function(error, id) {
if (error)
return alert(error.reason);
$('#npModal').modal('hide');
$('#npModal').on('hidden.bs.modal', function (e) {
Router.go('newFields', {});
})
});
});
Anyone have any ideas? Thanks!!
You have missed a return statement. function () {Orgs.findOne(this.params._id)} should be function () {return Orgs.findOne(this.params._id)}. Further more, this inside this function won't refer to what you want, so you can't use this.params. And why do you subscribe to a subscription as a data context property? Do it in the waitOn function instead.

Resources