$scope undefined in Angularjs - angularjs

I'm creating an Angular app for learning (I'm all new to Angular) and currently stuck at this point.
Following is my Angular controller
cookingPad.controller('RecipeCreateController', function($scope, $http) {
$scope.recipeSave = function($scope, $http){
//code
};
});
Following is my form
<form id="signup-form_id" ng-submit="recipeSave()">
//some html
<input type="text" name="name" ng-model="recipeFormData.name" id="name" class="form-control input-lg no-border-radius" placeholder="Name">
// some more html
<button class="btn btn-lg btn-success" id="save1" type="submit"><i class="fa fa-save"></i> Save</button>
</form>
So when I enter something in the text box and click save it comes inside the recipeSave function. but when I check the $scope variable with chrome dev tools, it shows it as
$scope
undefined
What could be the reason? Everything else in my Angular works im on Angular 1.2.4, I found several SO questions but none of them works for me.

Don't re-declare the controller args in recipeSave:
$scope.recipeSave = function() {
Make that change and things should start working. Your template is explicitly invoking recipeSave() with no arguments, and you want to access your controller arguments via closure anyway, which will work fine.

This is due to the recipeSave method having $scope and $http as arguments. Dependency Injection works on the Controller/Service/Filter/etc level, atributes from different scopes as recipeSave won't solve dependency injection.
In other words, on the view you are not passing parameters when you execute the recipeSave function, so the function gets undefined as the value of both parameters.
Cheers

Related

Can't access form from inside AngularJS controller

I am trying to manually reset a form from inside an AngularJS controller but I can't access it using either $scope, or using controllerAs. When I log $scope.SupportForm, it returns undefined.
HTML
<form name="supportForm" id="supportForm" novalidate>
<label for="message">Message</label>
<textarea name="message" id="message" model="$ctrl.formData.message" maxlength="5000" required></textarea>
<button type="submit" data-ng-click="$ctrl.submitForm($ctrl.formData)" data-ng-disabled="supportForm.$invalid">
Request support
</button>
</form>
Contoller
function GeneralSupportController($scope, $state, $timeout, $stateParams, SupportService, $uibModal) {
var vm = this;
vm.formData = {};
vm.submitForm = submitForm;
function submitForm(data) {
console.log('$scope.supportForm : ', $scope.supportForm)
}
}
I have also tried adding ngModel to the form, but it also doesn't work.
Question
Any idea why the form isn't being assigned to the scope?
Form is assigned to scope in your code. (https://plnkr.co/edit/7eYvApaW36DrRmvK >> it works) I guess actually you have following:
<div ng-if="...">
<form name=...
In this case form is assigned to nested scope of ng-if not controller scope. You have several solutions:
pass form to submit function $ctrl.submitForm(supportForm... useful when u have several forms
put form into controller <form name="$ctrl.supportForm" do it when u have one form

Loading a field value without overwriting

I have several fields loaded within a directive call for a page, each of which should be loaded with prepopulated data from either a REST call or Local Storage.
Right now, the mechanism I use loads the field through $scope, but when the page finishes loading, the value itself is never populated. When loaded using a jQuery alter, the value is initalized, and then vanishes on page load. I am not sure what the cause is here, and being fairly new to Angular, I am not sure how to best work around this trivial measure.
The directive form markup is below:
<form name="testfield" ng-controller="testfieldApp" ng-submit="verify(testform)" novalidate>
<input type="text" name="testfield" id="testfield" ng-model='testfield' value="{{TestField}}" required />
</form>
The wrapping Controller
app.controller('testfieldApp', function ($scope, $window, $http, $localStorage) {
$scope.TestField = "Test Name";
//Additional $scope. methods exist for validation and submit, omitted
});
You only need ng-model, but it is case sensitive. ng-model will override whatever you have in value. Try this instead:
<input type="text" name="testfield" id="testfield" ng-model="TestField" required />

Scope variable is changing unexpected manner Angular JS

I am a beginner in AngularJS. Recently tried out below code.
HTML Tag:
<div ng-app="myApp">
<input type="text" ng-model="message" />
<h1>{{ message }}</h1>
<div ng-controller="ctrlOne">
<input type="text" ng-model="message" />
<h1>{{ message }}</h1>
</div>
<div ng-controller="ctrlTwo">
<input type="text" ng-model="message" />
<h1>{{ message }}</h1>
</div>
</div>
JS Script:
var app = angular.module("myApp", []);
app.controller("ctrlOne", function($scope) {
console.dir($scope);
});
app.controller("ctrlTwo", function($scope) {
console.dir($scope);
});
If you type in the text area. Each output print is unique. Even though I have used common variable to the $scope element.
Can any one please explain,
1. what is happening internally?
2. How angular is handling this scope?
If you can help with step wise advice explaining, so that it is easy for beginner like us to understand.
Your time spent on this highly appreciated. Thanks in advance.
Please find JSFIDDLE Link Below:
Code Snippet example on $scope
Please check the console. Its is showing undefined.
Even though you have used a common variable, but both of them are under the scope of different controller.
One is under the scope of controller ctrlone and other is under the scope of controller ctrltwo.
When you create a controller, angular creates a separate scope pertaining to that controller alone. So even if the names of variables are same but if they are defined on two different scope, they will have unique values.
However, if you want to have a variable with same value in both controller, then you will have to define that variable on $rootScope because $rootScope is created once per app.
Inside your controller, you can retrieve the value like this:
console.log($scope.message);
This will give you the value of message as you typed in the input box.

How get form by name in $scope?

How to get form by name in $scope?
Test example:
<div ng-controller="solod">
<form name="good_f">
<input type="text" name="super">
</form>
</div>
<script>
function solod($scope){
console.log($scope.good_f) //undefined
}
</script>
Is it possible?
Thank you
You usually don't want the controller to access the form like this, that's coupling the controller to the structure of the view too tightly. Instead, pass the form to the controller like this...
<div ng-controller="solod">
<form name="good_f" ng-submit="submit(good_f)">
<input type="text" name="super">
</form>
</div>
<script>
function solod($scope){
$scope.submit = function(theForm){
console.log(theForm)// not undefined
console.log($scope.good_f) // will exist now also
};
// do stuff in a watch
$scope.$watch("good_f", function(formVal){ console.log(formVal);});
}
</script>
Otherwise, if you just want to track the value of the text input, give it an ng-model
Edit:
On further research, $scope will have good_f as a property, just not when you're logging it in the constructor. You could set up a watch on good_f if you wanted, but I still think you should pass it in.
name (optional) string Name of the form. If specified, the form
controller will be published into related scope, under this name.
https://docs.angularjs.org/api/ng/directive/form
Another possible way is to use ng-form, this will help you to access the form via scope easily.
<div ng-controller="solod">
<ng-form name="good_f">
<input type="text" name="super">
</ng-form>
</div>
Script code in your controller:
EDIT:
As JeremyWeir mentioned, to solve your problem you can use $timeout service of angularjs
function solod($scope){
$timeout(function(){
console.log($scope.good_f);
});
}
Caution: Don't use this - seriously
Angular is not jQuery.
As par as your question is concerned you can use $element in your controller(if you are not concrete with the $scope usage for this use case) -
myApp.controller("myCtrl", function($scope, $element){
alert($element.find('form').attr('name'));
$scope.myFormName = $element.find('form').attr('name');
});
PLNKR DEMO

From AngularJS how to pass data from a controller+template to another controller+template?

I'm building an application with AngularJS and Slim PHP framework for the backend, now I completed my 1st form and created a route to the template for it. Now my problem arise when I want to pass my data to another controller, I need to pass the data to another controller+view(template), I don't want to pollute my first view neither the controller of it and so I really want/need to pass the data to another controller which I could play with my data and another form (the 2nd form is for calculation and other stuff)...So you can call the first controller a pre-save, while the real data save (backend to DB) will only happen in the second controller+template. Here is a short of my 1st template view that has the form:
<form novalidate id="formAdd" name="formAdd" class="form-horizontal well col-md-7 col-md-pull-5" method="post">
<fieldset>
<legend>Transaction form</legend>
<div class="form-group">
<label for="symbol" class="col-sm-4 control-label">Symbol</label>
<div class="col-sm-5 symbols">
<input type="text" name="symbol" class="form-control" ng-model="trsn.symbol" placeholder="symbol" required />
</div>
</div>
<div class="form-group">
<label for="accnt_id" class="col-sm-4 control-label">Account</label>
<div class="col-sm-5">
<select id="accnt_id" name="accnt_id" ng-model="trsn.accnt_id" class="form-control" required>
<option value="">...</option>
<option ng-repeat="account in trsn.accounts" value="{{account.accnt_id}}">{{account.accnt_name}}</option>
</select>
</div>
</div>
<!-- ....etc, etc.... -->
<div class="form-actions col-sm-8 col-sm-offset-4">
<button type="submit" name="save_btn" class="btn btn-primary" ng-disabled="formAdd.$invalid" ng-click="preSaveTrsn(trsn, formAdd)">Save transaction</button>
<button type="reset" class="btn btn-default">Cancel</button>
</div>
</fieldset>
</form>
then the app with the module and routes:
var investingApp = angular.module('investingApp', ['ngSanitize','ngResource', 'ngRoute'])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/new-trsn',
{
templateUrl: 'templates/StockTransaction.html',
controller: 'StockTransactionController'
});
$routeProvider.when('/presave-trsn',
{
templateUrl: 'templates/PreSaveTransaction.html',
controller: 'PreSaveTrsnController'
});
});
now inside my first controller is the presave function, which is empty since I don't know what to do with it so that I can send the transaction data to the next controller+view:
investingApp.controller('StockTransactionController',
function TransactionController($scope, $http, $location, $compile, $timeout, transactionDataService, dateFilter) {
// define some default variables
$scope.trsn = {};
$scope.trsn.symbol = "";
...
$scope.preSaveTrsn = function(trsn, formAdd) {
// what to put in here to transfer data to next controller????
};
and then my last controller, I have also nothing in there yet since I can't receive any data....but basically what I want to inject is the transaction data (trsn) which comes from 1st form/controller.
investingApp.controller('PreSaveTrsnController',
function MenuController($scope, $http, trsn) {
console.debug(trsn);
});
Does I have to put something inside the routeProvider somehow? ...or does I have to fill in something special inside the preSaveTrsn function inside my 1st controller??? I'm quite confused with this since all example I find are for saving right away to database, but I can't do that the way I build my app, it really has to be on the second controller for few reasons which I don't think I have to explain here.... Thanks for any help given :)
You may create a lightweight service - value
angular.module('investingApp').value('MySharedValue', {});
And then inject it in both controllers:
TransactionController($scope, $http, $location, $compile, $timeout, transactionDataService, dateFilter, MySharedValue)
And just to assign your shared value to it
$scope.preSaveTrsn = function(trsn, formAdd) {
MySharedValue.trsn = trsn;
};
There are 2 ways to achieve it. First is to declare your model object on $rootScope or on a scope which is parent to both of these controller scope. This way the data gets shared and the changes are available to both controller, irrespective of who makes it.
The second better approach is to create a service which tracks the model update. Inject this service into both the controller. Any controller can ask ask for the model from the service and update it. Since services are singleton, the model changes are shared across controller.
Like
angular.module("myApp",[]).factory('transactionService',[function(){
var service={};
var model={};
service.preSaveTrsn = function(trsn, formAdd) {
//set model here
};
service.getPreSaveTrsn=function() {
return model;
}
return service;
}]);

Resources