Pass ng-model from parent to controller - angularjs

I am trying to pass ng-model located in a different HTML scope to controller when a button is clicked. It works if the button is in the same scope as the ng-model, but I want to have the button in the header.
Case 1. This works:
HTML
<header>
</header>
<content>
<label>
<input ng-model="text">
</label>
<button ng-click="save(text)">
Save
</button>
</content>
Case 2. This does not work:
HTML
<header>
<button ng-click="save(text)">
Save
</button>
</header>
<content>
<label>
<input ng-model="text">
</label>
</content>
Controller
$scope.save = function(text) {
console.log(text); // Undefined in case 2.
};
To my understanding the ng-model is better suited pointing to an object key. So I tried this:
HTML
<header>
<button ng-click="save(text)">
Save
</button>
</header>
<content>
<label>
<input ng-model="obj.text">
</label>
</content>
Controller
$scope.save = function() {
$scope.obj = {};
console.log(obj.text); // Still undefined
};
How can I pass ng-model when the button is located in the header is clicked to controller?

Related

How can I change radio buttons to div?

I'm absolutely new to Angular.js, I got the file from someone to fix.
So the question is that I really want to change the div with clicking buttons, so I tried to search of it and i found the solution with radio button, but the thing is what i want to click is div.
So here is my code :
let vm = $scope
vm.isShown = function (color) {
return color === vm.color;
};
//this is the function in a controller
<div class="item">
<span class="group-name"
><p>PHASE 1.0</p>
Closed API Data Market</span
>
<input type="radio" ng-model="color" value="oneZero" /> 1.0
</div>
<div class="item">
<span class="group-name"
><p>PHASE 1.5</p>
Open API Data Market</span
>
<input
type="radio"
ng-model="color"
value="oneFive"
checked="checked"
/>
1.5<br />
</div>
</div>
</div>
<br />
<div class="servicePreparing" ng-show="isShown('oneZero')">
<img src="assets/img/serviceStop.jpg" />
</div>
<div class="select-list-area" ng-show="isShown('oneFive')">
I want to remove the inputs and want to click with div as class name as 'item'
You can see one example lives here: https://plnkr.co/edit/flMIhl6ugNUNXwpE
Also, what you have to do is set one variable (In the radio buttons were color), so in your AngularJS controller:
vm.color = '';
And set that value with ng-click in both divs, with the specific value, in your view you will have:
<div class="btn" ng-click="color = 'oneZero'">1.0</div>
<div class="btn" ng-click="color = 'oneFive'">1.5</div>
<div class="servicePreparing" ng-show="isShown('oneZero')">
One Zero Image Showed
</div>
<div class="select-list-area" ng-show="isShown('oneFive')">
One Five Image Showed
</div>

Toggle view with ng-click and ng-if

How do I toggle the view of an article by clicking a <button>?
<button ng-click="/* change view and button label */">Label</button>
<article ng-if="/* */">
<h1>{{title}}</h1>
<p>{{content}}</p>
</article>
<article ng-if="/* */">
<input type="text" value="{{title}}">
<textarea>{{content}}</content>
</article>
You need to maintain one scope variable showInputsArticleWithInput & do toggle it on click of button using ng-click directive.
As you want to change your button text for that you could use ng-bind directive with expression like ng-bind="showInputsArticleWithInput? 'Edit': 'Close'"
Markup
<button type="text" ng-click="showInputsArticleWithInput = !showInputsArticleWithInput"
ng-bind="showInputsArticleWithInput? 'Edit': 'Close'"></button>
<article ng-if="!showInputsArticleWithInput">
<h1>{{title}}</h1>
<p>{{content}}</p>
</article>
<article ng-if="showInputsArticleWithInput">
<input type="text" value="{{title}}">
<textarea>{{content}}</content>
</article>

Cannot reset form

I'm new to Angular and I have a simple retrieve password form with 1 email field and a submit button. I want to clear the form after the form has been submitted, but I can't seem to do it even after following tutorials/answers online.
I think it might be something I'm not understanding fundamentally, so if you could please let me know that would be great.
I'm using Angular v1.2.22
HTML (signin.forgotpassword.html)
<form name="forgotPasswordForm" class="form" role="form" ng-submit="forgetPasswordSubmit(forgetForm.email)" novalidate >
<div>
<label for="input-email" class="col-sm-2 control-label">Email</label>
<div>
<input name="email" ng-model="forgetForm.email" type="email" class="form-control" id="input-email" />
</div>
</div>
<div class="form-group">
<div>
<button name="submit" type="submit">Reset Password</button>
</div>
</div>
</form>
Angular (AuthController)
var forgetPasswordClear = function(){
var defaultForm = {
email: ''
};
// clear input
$scope.forgetForm = defaultForm; // Doesn't clear
// set form as pristine
$scope.forgotPasswordForm.$setPristine(); // Get Cannot read property '$setPristine' of undefined
};
$scope.forgetPasswordSubmit = function(email){
forgetPasswordClear();
};
----------EDIT----------
I'm not sure if it's because my form is sitting in a different ui view? My structure looks something like this:
HTML
<section data-ng-controller="AuthController">
<div data-ui-view>
Some content in there originally
<a ui-sref="signin.forgetpassword">Click here to get password</a>
</div>
</section>
Ui router
.state('signin.forgotpassword', {
url: '/signup/forgot-password',
templateUrl: 'modules/core/templates/signin.forgotpassword.html'
})
You set the wrong model:
Your model is 'forgetForm'
<input name="email" ng-model="forgetForm.email" type="email" class="form-control" id="input-email" ng-pattern="/.+\#.+\..+/" autofocus required />
current:
$scope.forget = defaultForm;
should be:
$scope.forgetForm = defaultForm;
EDIT TO ADDRESS NEW PROBLEM
It's because this is a child scope.
You need to use event emitters and listeners.
$broadcast -- dispatches the event downwards to all child scopes,
$emit -- dispatches the event upwards through the scope hierarchy.
Read more here: Working with $scope.$emit and $scope.$on

Communication between Angular.js controllers and Polymer custom elements

I'm using Angular.js on one of my projects and I want to combine it with Polymer. I have some problems with the comunication between Angular.js controllers and the Polymer custom elements.
What is my problem...
For example I have an AuthService, an AuthController which uses the AuthService to send requests to the backend (Node.js with Express) and a simple login form like this:
<form role="form" ng-submit="login()">
<div>
<label for="usernameInput">Username: </label>
<input type="text" name="usernameInput" id="usernameInput" placeholder="Username" ng-model="usernameInput" required>
</div>
<div>
<label for="passwordInput">Password: </label>
<input type="password" name="passwordInput" id="passwordInput" placeholder="Password" ng-model="passwordInput" required>
</div>
<div>
<label for="rememberMeInput">Remember me: </label>
<input type="checkbox" name="rememberMeInput" id="rememberMeInput" ng-model="rememberMeInput">
</div>
<input type="submit" name="loginSubmit" value="Log in">
</form>
Everiting is working fine in this format but I want to move the form inside a Polymer custom element like this:
<polymer-element name="cg-login-form">
<template>
<div layout vertical>
<div class="error hidden">{{ error }}</div>
<form role="form" layout vertical center>
<div>
<paper-input type="text" floatinglabel label="Username" value="{{ inputData.username }}"></paper-input>
</div>
<div>
<paper-input type="password" floatinglabel label="Password" value="{{ inputData.password }}"></paper-input>
</div>
<div layout horizontal center>
<paper-checkbox role="checkbox" checked="{{ inputData.rememberBe }}"></paper-checkbox>
<div>Remember me</div>
</div>
<paper-button label="Log in" raisedbutton role="button" on-click="??????"></paper-button>
</form>
</div>
</template>
<script>
Polymer('cg-login-form', {
inputData: {
username: undefined,
password: undefined,
rememberMe: false
}
});
</script>
</polymer-element>
My problem is: How to call the login method of the AuthController on form submit and I want the Polymer element to stay Angular.js independent.
I was thinking to fire a login event with the input data and to listen for this event inside the AuthController. Then the login event handler can call the AuthContoller's login method, but I can't get the sent data with the event.
This is how I'm firing the event inside the:
<paper-button label="Log in" raisedbutton role="button" on-click="{{ login }}"></paper-button>
Polymer('cg-login-form', {
inputData: {...},
login: function() {
this.fire('login', { loginData: this.inputData });
}
});
And this is how I'm listening for the login event inside the AuthController:
// In this way the detail and the data properties of the event object are undefined
angular.element("#loginForm").on('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
// In this way the detail and the data properties of the event object are undefined
$('#loginForm').on('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
// In this way the detail property of the event object is set with the sent data
document.getElementById('loginForm').addEventListener('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
// In this way the detail property of the event object is set with the sent data
document.querySelector('#loginForm').addEventListener('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
Why document.getElementById('loginForm').addEventListener() and document.querySelector('#loginForm').addEventListener() works and the other two ways doesn't work?
How can I get the sent data using jQuery or jqLite? I prefer to use them instead of using the html approach.
I will be glad if you tell me a better way for communication between Angular.js controllers and Polymer custom elements instead of events triggering.
Thank you very much and have a nice day
EDIT:
Also I can get the ng-login-form element from the DOM inside the AuthController and pass the AuthController's login method like a callback to some ng-long-form method. Then on form submit the ng-login-form can call the callback with the input data.
This will work too but I don't think that this is a good approach.
I solved it this way
In the paper-input add -- inputValue="{{ valData }}" --
for example
<paper-input label="name" id="name" class="label-input-full" inputValue="{{ valData }}">
</paper-input>
Add in button submit onclick event
for example
<paper-button class="btn-check" type="submit" icon="check" core-overlay-toggle on-click="{{fetchDataFromForm}}" >
</paper-button>
Finally in the scripts, add the function for send data to angular
For example
Polymer('name-element', {
fetchDataFromForm: function() {
USER_DATA = this.valData;
console.log(USER_DATA);
var scope = angular.element($("#angular-controller")).scope();
scope.$apply(function(){
scope.contacto = { varAngular: USER_DATA };
console.log(scope.contacto);
scope.angularFunction();
});
}
}
In Angular ... usually done
I hope to help you in something
Regards

AngularJS Dynamically Adding Control In Repeater to Form Causes Submit

I have a form which represents an object and an array of sub-objects contained in a repeater. I want to dynamically add sub-objects to the array. When I add a sub-object the form gets submitted unexpectedly.
See this example:
http://plnkr.co/edit/TUblgmb7N710nPL7s5tU?p=preview
My form looks like this:
<form ng-submit="handleSubmit()" ng-controller="TestController">
<div>Some Input: <input type="text"></div>
<div ng-repeat="obj in model.children">
<input type="text" ng-model="obj.text" />
</div>
<button ng-click="addChild()"> Add Child</button>
</form>
The controller looks like this...
Controllers.controller('TestController', ["$scope", function($scope) {
$scope.model = {
name: "Some Text",
children: []
};
$scope.handleSubmit = function() {
alert("Form Submitted!");
}
$scope.addChild = function() {
$scope.model.children.push({text:"Foo"});
}
}]);
Click the "Add Child" buttton. The UI is updated as expected but the form gets submitted.
I can work around this by putting the submit function in ng-click on the Save button instead of ng-submit on the form but this seems like unexpected behaviour. Can anyone explain?
The default attribute type The HTML button tag <button>My Button</button> triggers the submit event as <input type = "submit"...> does.
Now, following the idea of #GruffBunny, I have added a pInputType parameter to your method to show what button was clicked:
$scope.addChild = function(pInputType) {
$scope.model.children.push({text:"Foo", inputType : pInputType });
}
Then in the HTML block, the attribute inputTypewas added within the loop as follow:
<div ng-repeat="obj in model.children">
<hr />
<h3>{{obj.inputType}}</h3>
<div>New Input: <input type="text" ng-model="obj.text" /></div>
</div>
Finally, here are the buttons for testing the code:
<!-- With Input Type -->
<h2>Input type Button</h2>
<input type="button" ng-click="addChild('Input type Button')" value="Btn Add Child" />
<hr />
<!-- With Normal Anchor -->
<h2>HTML Anchor</h2>
Add Child Link
<hr />
<!-- Adding Bootstrap -->
<h2>HTML Bootstrap Anchor</h2>
Add Child Link
<hr />
<!-- Button Tag -->
<h2>HTML Button Tag (Triggers SUbmit Events)</h2>
<button ng-click="addChild('Triggers Submit Events')">Add Child</button>
<hr />
Here is the complete plunker: http://plnkr.co/edit/N4hSjG
For further information about this behavior, you can read this Stack Overflow question: <button> vs. <input type="button" />. Which to use?
I hope it could be useful this explanation for anyone.

Resources