New scope on form - angularjs

I have an element, which has an ng-controller, that has some values attached to scope. I have a form element inside this one, which I would like to have create its own child scope. The use case: I want the form to be populated with the parent scope's variables intially, but not have changes on the form propagate up until the user clicks the form's "submit" button.
How would I force the form to have a child scope that inherits from the parent element's scope?

Common approach in your situation is to use "new" object. You use, for example, newuser.name as model for input and then createUser(newuser) on submit.
Here is plnkr demo: http://plnkr.co/edit/3x7T2JgV5yxb9iJqYMYq?p=preview

Related

Why Angular 1 form validation not works without ng-model

I am trying to implement the basic angular form validation. I have implemented the same. But I am curious to know, why it does not works if I am not using ng-model.
Link for plunker to show the same behaviour
ngModel directive holds an instance of NgModelController containing the services for data-binding, validation, CSS updates, and value formatting and parsing. If ngModel itself is not there, validation will not work.
For form validation to work you need both form instance which can be published to scope using name attribute and the form input control (ngModel). The below description from Angular documentation explains that:
A form is an instance of FormController. The form instance can
optionally be published into the scope using the name attribute.
Similarly, an input control that has the ngModel directive holds an
instance of NgModelController. Such a control instance can be
published as a property of the form instance using the name attribute
on the input control. The name attribute specifies the name of the
property on the form instance.
This implies that the internal state of both the form and the control
is available for binding in the view using the standard binding
primitives.
This allows us to extend the above example with these features:
Custom error message displayed after the user interacted with a
control (i.e. when $touched is set) Custom error message displayed
upon submitting the form ($submitted is set), even if the user didn't
interact with a control
Because without the ng-model, the input elements aren't bound to anything within your application's scope.
Angular has own context model. (scope or something else) If you treat form outside Angular world, form can't get any information in Angular point of view.
If you doesn't want to use ng-model, use plain javascript validation method.
ng-model="value" defines that the value of that particular element is from angular's context. It checks for the value in the scope where the element is declared. For example, we have onclick="call()" and ng-click="call()" methods. The onclick event search for the function that is outside of angular context, ng-click event search for the function in the scope.
<div ng-app="app" ng-controller="Ctr" onclick="call()" ng-click="call()"></div>
<script>
function call(){
console.log('out of angular');
}
angualr.app('app', function($scope){
$scope.call = function(){console.log('insode angular')}
})
</script>
In the above code if you remove onclick, then ng-click prints 'inside angular', if you remove ng-click, then onclick prints out of angular. If both will be there, both will be called and prints.
In the same way, if you remove ng-model, you will loose the control over the value of input in angular context and $error, $invalid doesn't know what to validate.

Ng-if and custom directives

I've been creating custom directives that involve initialization of data on load. Since this initialization depends on the state of scope objects from the parent bound to the isolate scope within my directives, I've been enclosing the directives in ng-if statements, so they are only rendered in the DOM, and therefore initialized, once the appropriate parent scope objects are created.
Ng-if seems preferable because the directives have various API calls bound to $watches that I would prefer to not trigger until the data is valid.
For example, I have a directive that provides an interface for editing a scheduled event. The parent page allows users to select an event for editing, or to create a new event. Creating a new event is done in a way that allows the user to select a variety of values to pre-populate the event object with (start dates, event type, whether the event is tied to another object in the database, etc.).
The ng-if wrapping the directive gets set to true when the user makes the selections necessary for working with the event, and the event (either an existing event, for edits, or a framework for an event created by a custom service, for adds) is bound to the isolate scope of the directive.
This prevents the $watches from triggering until the valid event is bound to the directive, and also allows me to initialize some variables local to the directive for validation and data manipulation of the event.
The problem I'm running in to is that enclosing the directive in an ng-if isolates the isolate scope.
For example, a start time for the event is something that may, or may not, be specified by the user when they create the new event from the controller. If they don't, I want to calculate a default start time based upon other variables within the directive. If they do, then I want to use that value.
The way I'm doing this is to bind a scope variable from the controller to the isolate scope of the directive:
scope: {
editEvent: '=',
overrideTime: '='
}
This is passed as an attribute of my directive:
<add-edit-event ng-if="viewEdit" event="editEvent" override-time="overrideTime">
</add-edit-slot>
Once the directive creates the new event (or cancels out), I want to reset that overrideTime in the parent scope to null.
To do that from within my directive, however, I can't rely on the two-way binding to work without traversing up past the ng-if scope, thus:
scope.$parent.$parent.overrideTime = null;
I keep running into situations like this, where the fact that the directive is enclosed in an ng-if causes complications with the scope, which makes me feel like there's a problem with my general approach.
Is there a better way of handling conditional initialization and loading of custom directives, or is enclosing them in ng-if statements okay, so long as I deal with the interposing ng-if's scope appropriately?

Ionic framework with AngularJs : Can a modal have the same controller as the view that launches the modal?

I am trying to build out a multistep form for a complex object. I use the modal to section out parts of the form. The Ionic examples I could find, appear to assign a different controller to the modal. I would like to keep the view plus all the modals it launches, all of them associated with one controller. Is that possible? I tried assigning to the modal view ng-controller="viewCtrl" where viewCtrl is also the controller of the starting view that launches the modal, but it appears to hang chrome with a high CPU which subsequently necessitates killing the chrome tab.(some sort of cyclic effect by calling the same controller??)
Your advice/insight would be welcome.
I assume that your modal is a directive.
I also assume that you have it placed inside the view (controller scope).
If the above are correct than the directive inherits the $scope properties and methods from the parent controller (a general thing in angular), unless your directive has an isolated scope (if you have the scope property in the directive set to anything but false).
If your directive has an isolated scope you can still pass data from the parent using attributes on the directive. If you want to pass something from the directive to the parent you can use $emit.
You can also access the parent from the directive using $parent but I would suggest against it.

Building a reusable AngularJS directive with two-way databinding set through code

I'm trying to build a reusable directive that shows a dialog box when a button is clicked and allows the user to customize an array of strings. I have this working fine in a single-use-case scenario, but I'm trying to figure out if I can create two-way data binding through code, so that I can use a single instance of this directive multiple times with different arrays of strings.
In my HTML, I have the directive (note the lack of binding to a particular array):
<my-array-dialog control='arrayDialog'></my-array-dialog>
I'm exposing a shared control object with a showDialog method on it that causes the dialog to be shown. An example of that pattern is: http://plnkr.co/edit/MqN9yS8R5dnqTfjqldwX?p=preview
What I want to do is have two-way data-binding with the parent controller passing in the data into my showDialog method. I'm unsure how to configure this though, or even if it is possible.
In my directive, I have the following:
$scope.control = {
showDialog: function (arrayData) {
// Ideally, this would create two-way data binding
$scope.arrayData = arrayData;
// Manipulate the DOM here to show the dialog
}
}
Ideally, changes to $scope.arrayData would be reflected in the calling code's arrayData. Again, the reason I'm not setting this up as an attribute is because I want to call this dialog multiple times with different data and to avoid having multiple dialog directive instances.
Is it possible to set up the two-way data binding in this manner, or am I going about this all wrong?
Absolutely! Check out the intimidating yet incredibly helpful AngularJS docs page on $compile. In particular, what it sounds like you'd like to do is create a two-way binding between a parent scope variable and a variable in the local scope of the directive.
When defining a directive, you can specify a scope object. You'll want to create an isolate scope (for reusability) and use the # feature to create the two-way bindings with the HTML attributes.
From the $compile docs:
= or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given and widget definition of scope: { localModel:'=myAttr' }, then widget scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel and any changes in localModel will reflect in parentModel.

AngularJS checkbox placed inside ng-repeat not binding

I have a checkbox (bound to a model), placed inside an ng-repeat tag which iterates over a list.
I want to send a value "YES" or "NO" depending on whether the box is checked or not to the controller using the ng-true-value and ng-false-value attributes.
But for some reason, the $scope.value2 is not getting updated in the controller.
Here is a jsFiddle with my problem:: http://jsfiddle.net/HmvgW/
Note: If I place the checkbox outside the ng-repeat tag, the YES/NO value is sent correctly to the controller.
How do I send a value to checkbox clicked value to the controller if I place it inside the ng-repeat tag?
Thanks!
It's a scope issue. ng-repeat creates a new child scope with each loop. If you want to access the parent scope from within the child, you can do so with $parent.value2.

Resources