Update ng-model from controller - angularjs

Hopefully this is pretty simple, but my brain just isn't working at the moment...
I have a form like this:
<div class="control-group">
<label class="control-label" for="CN_PREF_NAME_J04">Name on Card:</label>
<div class="controls">
<input type="text" name="CN_PREF_NAME_J04" id="CN_PREF_NAME_J04" ng-model="formData.CN_PREF_NAME_J04" />
</div>
</div>
and I have a basic controller like this:
app.controller("CloseCallSpoke", function($scope){
$scope.formData = angular.copy($scope.data);
}
This will automatically assign the entire formData object whatever is in my data object.
How can I just assign CN_PREF_NAME_J04?
i tried:
$scope.formData.CN_PREF_NAME_J04 = angular.copy($scope.data.CN_PREF_NAME_J04);
but I get "$scope.formData is undefined.
Please help.

try this:
$scope.formData = { CN_PREF_NAME_J04 : angular.copy($scope.data.CN_PREF_NAME_J04) };
That way $scope.formData is initialized with an object that has the CN_PREF_NAME_J04 property you're looking for

Related

'or', 'and' in ng-model angularjs

I have a list of items, some of them has property value, some has property default. And I need to bind it into the input[text] with ng-repeat.
Array is looks like:
$scope.arr = [
{value:'name'},
{value:'dog'},
{default:'cat'},
{value:'lastName'},
{default:'ring'}
];
And in html:
<div ng-repeat='item in arr'>
<input type='text' ng-model='item.value || item.default'>
</div>
It works, but I have error message in console "[ngModel:nonassign] http://errors.angularjs.org/1.5.8/ngModel/nonassign?p0=item.value%20%7C%7CNaNtem.default&p1=%3Cinput%20type%3D%22text%22%20ng-model%3D%item.value%20%7C%7C%item.default%22%20class%3D%22ng-pristine%20ng-untouched%20ng-valid%22%3E". Because ng-model doesn't work with expression..
Perhaps there is another way to solve it?
Plnkr example
You can do it this way:
<div ng-repeat='item in arr'>
<input type='text' ng-hide='item.default' ng-model='item.value'>
<input type='text' ng-show='item.default' ng-model='item.default'>
</div>
Plunker example.
You can try to create a second array, using only single type of object and bound it to the view.
Then, you can watch for changes and re-assign values to your original array.
It is more a MVVM approach (creating a "viewModel") that intermediate between the controller model and the view.
$scope.valueOrDefault = function (item){
return item.value|| item.default;
}
and HTML
<div ng-repeat='item in arr'>
<input type='text' ng-model='valueOrDefault(item)'>
</div>

Get pristine value in Angular controller

I need to be able to see in the Angular controller if the datepicker is pristine or not. Tried all sorts of things including sending the pristine value in a method but cannot get this value. Below is the view code:
<form name="myForm">
<!-- Datepicker From -->
<div class="small-6 medium-5 large-2 columns" ng-if="vm.subViewActive">
<div class="input-group">
<input name="valuationDatePickerFrom" ng-model="name" type="text" class="datepicker" id="valuationDatePickerFrom" placeholder="DD/MM/YYYY" pikaday="vm.datePickerFrom" on-select="vm.selectStartDate(pikaday)" year-range="{{ vm.yearRange }}" >
<div class="input-group-addon">
<label for="valuationDatePickerFrom" class="postfix">
<i class="fa fa-calendar"></i> From
</label>
</div>
</div>
</div>
</form>
and then I also tried :
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
in my controller but cannot get the pristine value. Read lots of posts here but mainly to do with CSS classes and front-end control or setting the pristine state from the backend not getting or checking the pristine state.
Thanks anybody that can help.
You are using:
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
but your form's name is not myForm.
Change <input name="name"... <input name="valuationDatePickerFrom"...
Then you can use:
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
Also, the controller is getting called before the view is created, so no myForm exists at the time the controller runs. Try adding a $timeout like so:
$timeout(function() {
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
}, 100);
plunkr
The above solution only works on page load, but you need to know this value when the page is being used. Instead pass the value to the controller when an action happens:
<form name="myForm">
<input type="text" name="valuationDatePickerFrom" ng-model="valuationDatePicker" ng-blur="alerty(myForm.$pristine)">
</form>
.controller('MainController', function($scope) {
$scope.alerty = function(isPristine){
alert('isPristine: ' + isPristine);
};
https://plnkr.co/edit/f0EWvYmoXCn8UOH3QCfE?p=preview

How to add a new value to a list with md-autocomplete?

I want to use md-autocomplete to search for an object in an array. If the object is found I want an edit form to be populated, but if the object is not found, I want the user to be able to add a new one using the same form.
For example, I have an array of contacts: [{name: string, email: string}...].
Then in my template:
<md-autocomplete
md-selected-item="$ctrl.newContact"
md-search-text="$ctrl.searchString"
md-selected-item-change="$ctrl.selectedItemChanged(item)"
md-items="item in $ctrl.getContactsByFullName($ctrl.searchString)"
md-floating-label="Contact's Name"
md-item-text="item.fullName">
</md-autocomplete>
<md-input-container>
<label>Email</label>
<input type='email' ng-model='$ctrl.newContact.email/>
</md-input-container>
When I enter a new value in Contact's name, tab to email and enter a value in email, the value of $ctrl.newContact.fullName becomes an object.
What am I doing wrong here? I've fiddled and codepenned but can't seem to get it right. Does anybody have a working example please?
Why not use md-search-text value inside the controller, then do with the value whatever you desire...Something like:
md-search-text="searchString"
Ctrl:
console.log($scope.searchString);
//You can do with the value whatever you want!
Not sure if thats what you needed...
I made a simple example.
https://jsfiddle.net/relferreira/faqsg514/1/
What you did wrong is that you defined the selected item as $ctrl.newContact, been each item an Object.
Controller:
angular.module('app', ['ngMaterial']);
angular.module('app')
.controller('MainCtrl', mainCtrl);
function mainCtrl(){
var vm = this;
vm.newContact = {};
vm.searchString = '';
vm.selectedItemChanged = selectedItemChanged;
vm.getContactsByFullName = getContactsByFullName;
vm.contacts = [
{name: 'Renan', email:'asldfk#.com'},
{name: 'Renan', email:'asldfk#.com'},
{name: 'Renan', email:'asldfk#.com'}
];
function selectedItemChanged(){
vm.newContact.fullName = vm.selectedContact.name;
}
function getContactsByFullName(name){
return vm.contacts;
}
}
HTML
<div ng-app="app">
<div data-ng-controller="MainCtrl as mainVm">
{{mainVm.newContact}}
<md-autocomplete
md-selected-item="mainVm.selectedContact"
md-search-text="mainVm.searchString"
md-selected-item-change="mainVm.selectedItemChanged()"
md-items="item in mainVm.getContactsByFullName($ctrl.searchString)"
md-floating-label="Contact's Name"
md-item-text="item.name">
<md-item-template>
<span md-highlight-text="mainVm.searchString">{{item.name}}</span>
</md-item-template>
</md-autocomplete>
<md-input-container>
<label>Email</label>
<input type='email' data-ng-model="mainVm.newContact.email"/>
</md-input-container>
</div>
</div>
for those who are looking to achieve the same check this fiddle
Approach:
Basically it attach a new model whenever md-search-text-change event occured and also remove the garbage model.
html code
<md-autocomplete
...
md-search-text="searchString"
md-search-text-change="selectedItemChanged(searchString)
...
</md-autocomplete>
angular code
function selectedItemChanged(searchString){
vm.contactArray.splice(actualLength,currentLength-actualLength)
vm.newModel = {};
vm.newModel.name=searchString;
vm.newModel.email='test'
vm.contacts.push(vm.newModel)
}

Angular setting form with scope?

What I want is a form that I can use for both creating and updating. So I pass before showing
$scope.form = {};
$scope.car = null;
$scope.getCar = function(hash) {
$http.get('/cars/'+hash).success(function(car) {
$scope.car = car;
$scope.form = car;
});
};
As you can see I add the result of the get to both car and form.
Now I'm opening the View:
<h1>{{ form.name }} <small>shows correctly</small></h1>
But a line after that I'm trying almost the same:
<form class="list" ng-submit="createOrUpdateForm(form)">
<label class="item">
<span class="input-label">Name</span>
<input type="text" ng-model="form.name">
Here it's not shown... But when I add the same line after it like this:
<input type="text" ng-model="car.name">
This does work, but then I can't use the ng-submit anymore, because that references to form.
Form some reason I can't set the form scope?
You should not manual assigning anything to form. A "form" is not the same as the data you manage using the form. Neither the empty object {} nor car make sense in that context.
Give the form a name, this will allow angular to assign it to a scope property.
<h1>{{ car.name }} <small>shows correctly</small></h1>
<form name="carForm" ng-submit="createOrUpdateForm(carForm)">
<label class="item">
<span class="input-label">Name</span>
<input type="text" ng-model="car.name">
$scope.createOrUpdateForm = function(form) {
if(form.$valid) {
console.log($scope.car.name);
// POST / PUT your data.
}
};

Firebase .push() Error and ng-model not working

I'm getting this error:
Error: Firebase .push failed: first argument contains undefined property 'price'
This is my controller:
angular.module('starter')
.controller('EditPicsController', function($scope,$location,$state) {
var itemsRef = new Firebase('https://myapp.firebaseio.com/items');
var itemprice = this.price
$scope.createItem = function(itemprice){
console.log(itemprice);
var newItemRef = itemsRef.push({'price':itemprice});
};
});
And my template:
<form>
<div class="list">
<label ng-model="price" class="item item-input item-stacked-label">
<span class="input-label">Price</span>
<input type="text" placeholder="$200.00" >
</label>
</div>
<button ng-click="createItem(price)" class='button button-dark'>
test-additem
</button>
</form>
my console.log output is blank.
What's going on here?
You should apply ng-model to input rather label.
<input ng-model="price" type="text" placeholder="$200.00" >
instead of
<label ng-model="price" class="item item-input item-stacked-label">
And in your code you've created a object of a class i.e. itemsRef. Its an object not an array. So because of this line itemsRef.push({'price':itemprice}); you're getting error. push is for arrays not for object.
You don't seem to use angularJS in its entirety.
As mentioned in the other answer you should set ng-model on input element rather than label because then you can leverage the angularJS philosophy of two-way data binding.
This is because user can interact with your client-side application in angularJS and can only change the value of HTML elements which are editable.
So those values are ng-model and will be binded to your controller and exposed through the glue called $scope in your controller.
So your HTML will be:
<form>
<div class="list">
<label class="item item-input item-stacked-label">
<span class="input-label">Price</span>
<input ng-model="price" type="text" placeholder="$200.00" >
</label>
</div>
<button ng-click="createItem()" class='button button-dark'>
test-additem
</button>
And your controller code:
angular.module('starter')
.controller('EditPicsController', function($scope,$location,$state) {
$scope.itemsRef = new Firebase('https://myapp.firebaseio.com/items');
$scope.createItem = function(){
var newItemRef = $scope.itemsRef.push({'price': $scope.price});
};
});
Also if your $scope.price is undefined then Firebase will complain because it wont allow you to save values which are undefined so set some Form validation or initialise the ng-model ($scope.price) with some value to test.
UPDATE: Your code $scope.itemsRef.push({'price': $scope.price}); for saving to Firebase is absolutely correct its just that Firebase doesn't like undefined in javascript so your model $scope.price needs to have a value to get this working
Since Firebase does not like undefined attributes like this:
item = { 'name': 'hot dog', 'price': undefined };
itemsRef.push(item);
I do a quick and dirty clean up of my objects before I push
for( let attr in item){
try {
if( item[attr] == undefined ) delete item[attr];
} catch(e){}
}
itemsRef.push(item);
which will push
{ 'name': 'hot dog' }
and firebase is happy :-) ..

Resources