Building dynamic angular forms with ngrepeat and ngform - angularjs

I'm using AngularJS 1,5 and the trick which I'm looking for is below.
For example, this is form:
<form name="main">
<div ng-repeat="user in users" ng-init="subForm='tags'+$index">
<ng-form name="{{subform}}"
<input type="text" name="username" ng-model="user.username" required/>
<input type="text" name="name" ng-model="user.name" required/>
<input type="email" name="email" ng-model="user.email" required/>
<input type="hidden" name="status" ng-model="user.status"/>
</ng-form>
</div>
</form>
I want to watch my models gathered from the ng-form child in the controller to check on their validity.
self.Scope.$watch('main[subForm].$valid', function ()
{
if (self.Scope.myform.subForm.$valid)
{
$scope.user.status = true;
}
});
Is there any way to implement something like that or should I create a custom directive.

In this sample we create our model as "forms" and send it to the directive, the parent form is valid if one of that forms is complete, by complete each form the user state will change
index.html
<div class="container" ng-app="app" ng-controller="ctrl">
<form name="parent_form">
<ng-form data-form="parent_form" data-list="forms"></ng-form>
<button type="submit" class="btn btn-default" ng-disabled="parent_form.$invalid">Submit</button>
</form>
</div>
app.js
var app = angular.module("app", []);
app.controller("ctrl", function ($scope) {
$scope.forms = [
{ name: "form1", isValid: false },
{ name: "form2", isValid: false }
];
});
ngForm.html
<div name="form_{{form.name}}" ng-repeat="form in list">
<h3>{{form.name}}</h3>
<div class="form-group">
<label for="username">username</label>
<input type="text" class="form-control" id="username" name="username" ng-model="form.user.username" ng-required="true" />
</div>
<div class="form-group">
<label for="name">name</label>
<input type="text" class="form-control" id="name" name="name" ng-model="form.user.name" ng-required="true" />
</div>
<div class="form-group">
<label for="email">email</label>
<input type="email" class="form-control" id="email" name="email" ng-model="form.user.email" ng-required="true" />
</div>
<label>user state is:</label>{{form.user.status}}
<hr />
</div>
ngForm.js
Directive with form handler
app.directive("ngForm", function ($filter) {
return {
restrict: 'E',
templateUrl: "ngForm.html",
scope: {
list: "=",
form: "="
},
link: function (scope) {
var isValid = function (list) {
var hasUser = $filter("filter")(list, { hasUser: true }, true);
if (hasUser.length >= 1) {
scope.form.$invalid = false;
} else {
scope.form.$invalid = true;
}
angular.forEach(list, function (item) {
if (angular.isDefined(item.user)) {
if ((angular.isDefined(item.user.username) && item.user.username !== null) &&
(angular.isDefined(item.user.name) && item.user.name !== null) &&
(angular.isDefined(item.user.email) && item.user.email !== null)) {
item.user.status = true;
item.isValid = true;
item.hasUser = true;
} else {
item.user.status = false;
item.isValid = false;
item.hasUser = false;
}
}
});
}
scope.$watch("list", function (nVal) {
if (nVal) {
isValid(nVal);
}
}, true);
}
}
});

Related

Get form input value from angularjs

I'm using Angularjs to submit the form then pass the value to my laravel function.
This is my HTML code
<form class="form-horizontal" method="post" name='form' novalidate ng-submit="submit()" ng-controller="syncApiCtrl">
<div class="col-lg-10">
<div class="input-group">
<input type="text" class="form-control" id="name" name="name" placeholder="Your_name">
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<input type="submit" name="sale" value="Sync Sale" class="btn btn-primary"></input>
<input type="submit" novalidate ng-click="sync_product(record)" name="product" value="Sync Product" class="btn btn-primary"></input>
</div>
</div>
</form>
This is my JS
$scope.submit = function () {
//$scope.form.$submitted = true;
// proceed if form valid
if ($scope.form.$valid) {
// is loading
$scope.loading = true;
// prepare data packet
var data = {};
angular.forEach($scope.form, function (v, k) {
if (k.indexOf('$') < 0 && typeof v.$dirty !== 'undefined' && v.$dirty) {
data[k] = v.$modelValue;
}
});
}
};
This is my laravel function
public function sync_sale() {
$name= preg_replace('/[^A-Za-z0-9\_]/', '', Input::get('name'));
Debugbar::info($name);
}
My laravel function always can't get the value after user submit a form.
You should have bound your input to a ng-model. This one is working. You should use data binding methods in angularJs.
<input type="text" class="form-control" id="name" name="name" placeholder="Your_name" ng-model="name">

My AngularJS 1.5 component called booking-info isn't populating the input fields in my form with booking data

I have a form inside a bookingEdit component and a bookingInfo component containing the form's input fields. The fields inside bookingInfo component aren't being populated with the booking data. How can I get these fields to be populated using my booking-info and booking-edit components?
booking-edit.template.html
<form name="$ctrl.form" ng-submit="$ctrl.updateBooking()">
<fieldset>
<legend>Edit Booking</legend>
<booking-info booking="$ctrl.booking"></booking-info>
<button class="btn btn-success" type="submit">Save</button>
</fieldset>
</form>
booking-edit.component.js
'use strict';
angular.
module('bookingEdit').
component('bookingEdit', {
templateUrl: 'booking-edit.template.html',
controller: ['BookingService','$location',
function (BookingService,$location) {
let self = this;
self.$routerOnActivate = function(next, previous) {
self.booking = BookingService.get({ id: next.params.id });
};
self.updateBooking = function () {
BookingService.update({ id: self.booking.bookingId }, self.booking)
.$promise
.then(
function () {
$location.path('/list');
},
function (error) {
}
);
};
}
]
});
booking-info.component.js
angular.module('app').
component('bookingInfo', {
templateUrl: 'booking-details.html',
bindings: {
booking:'<'
},
controller: function(){
let self = this;
}
});
booking-details.html
<div class="form-group">
<label for="contactName">Contact Name</label>
<input required type="text" class="form-control" ng-model="booking.contactName">
</div>
<div class="form-group">
<label for="contactNumber">Contact Number</label>
<input required type="tel" class="form-control" ng-model="booking.contactNumber">
</div>
You seem to forgot the $ctrl in booking-details.html
<div class="form-group">
<label for="contactName">Contact Name</label>
<input required type="text" class="form-control" ng-model="$ctrl.booking.contactName">
</div>
<div class="form-group">
<label for="contactNumber">Contact Number</label>
<input required type="tel" class="form-control" ng-model="$ctrl.booking.contactNumber">
</div>

Fields values generated using ng-repeat is not getting while submit

Template for form submission. This page will display the form template. Initially it shows the TItle,Full Name. On clicking the 'Add Tags' link new input fields is been generated for entering tags.
On submit, the field input(story.tag) is not been included on RequestPayload
<form novalidate ng-submit="save()">
<div>
<label for="title">Title</label>
<input type="text" ng-model="story.title" id="title" required/>
</div>
<div>
<label for="firstName">Full Name</label>
<input type="text" ng-model="story.fullname" id="fullname" required/>
</div>
<div ng-controller="Note" >
<div ng-repeat="story in items ">
<label>Tag {{$index+1}}:</label>
<input type="text" ng-model="story.tag" id="tag" required/>
</div>
<a ng-click="add()">Add Tags</a>
</div>
<button id="save" class="btn btn-primary">Submit Story</button>
</form>
script :- app.js
angular.module("getbookmarks", ["ngResource"])
.factory('Story', function ($resource) {
var Story = $resource('/api/v1/stories/:storyId', {storyId: '#id'});
Story.prototype.isNew = function(){
return (typeof(this.id) === 'undefined');
}
return Story;
})
.controller("StoryCreateController", StoryCreateController);
function StoryCreateController($scope, Story) {
$scope.story = new Story();
$scope.save = function () {
$scope.story.$save(function (story, headers) {
toastr.success("Submitted New Story");
});
};
}
//add dynamic forms
var Note = function($scope){
$scope.items = [];
$scope.add = function () {
$scope.items.push({
inlineChecked: false,
tag: "",
questionPlaceholder: "foo",
text: ""
});
};
}
The story object inside ng-repeat is in another scope. This JSFiddle should do what you are looking for.
<div ng-app>
<div ng-controller="NoteCtrl">
<form novalidate ng-submit="save()">
<div>
<label for="title">Title</label>
<input type="text" ng-model="story.title" id="title" required/>
</div>
<div>
<label for="firstName">Full Name</label>
<input type="text" ng-model="story.fullname" id="fullname" required/>
</div>
<div ng-repeat="story in items">
<label>Tag {{$index+1}}:</label>
<input type="text" ng-model="story.tag" required/>
</div> <a ng-click="add()">Add Tags</a>
<button id="save" class="btn btn-primary">Submit Story</button>
</form>
<div ng-repeat="test in items">
<label>Tag {{$index+1}}: {{test.tag}}</label>
</div>
</div>
</div>
The NoteController:
function NoteCtrl($scope) {
$scope.story = {};
$scope.items = [];
$scope.story.tag = $scope.items;
$scope.add = function () {
$scope.items.push({
inlineChecked: false,
tag: "",
questionPlaceholder: "foo",
text: ""
});
console.log($scope.story);
};
}

angularfire using $loaded how to access data in a directive

This post is a follow up of
this
(the goal is set img to visibily and set the src)
html
<form class="form-horizontal" role="form" name="form" data-ng-submit="add()">
<div class="form-group">
<input type="text" name="title" tabindex="1" class="form-control" placeholder="{{ 'items.form.title' | translate }}" data-ng-model="item.title" required="required" data-ng-minlength="3" data-ng-maxlength="25" user-feedback />
</div>
<div class="form-group">
<input type="text" name="ingredients" tabindex="2" class="form-control" placeholder="{{ 'items.form.ingredients' | translate }}" data-ng-model="item.ingredients" required="required" ng-pattern="/^\w(\s*,?\s*\w)*$/" user-feedback />
</div>
<div class="form-group">
<input type="text" name="price" tabindex="3" class="form-control" placeholder="{{ 'items.form.price' | translate }}" data-ng-model="item.price" required="required" data-smart-float user-feedback />
</div>
<div class="form-group">
<button type="button" tabindex="4" class="btn btn-default btn-lg" item="item" data-uploader>{{ 'items.form.upload' | translate }}</button>
<input type="text" name="url" style="display:none;" required="required" data-ng-model="item.url" />
</div>
<div class="form-group form-no-required clearfix">
<div class="pull-right">
<button type="submit" tabindex="5" class="btn btn-primary" data-ng-disabled="form.$invalid">{{ 'items.form.submit' | translate }}</button>
</div>
</div>
</form>
js
app.controller('ItemsUpdateController', function ($scope, item, Items, $state) {
item.$loaded().then(function(data) {
$scope.item = data;
});
$scope.add = function() {console.log($scope.item);
/* Items.update(item.$id,$scope.item).then(function () {
$state.transitionTo('items');
});*/
}
});
app.directive('uploader', function() {
return {
restrict: 'A',
scope:{
item: '='
},
link: function(scope, element, attrs) {
if (window.File && window.FileReader && window.FileList && window.Blob) {
var fileElem = angular.element('<input type="file" style="display:none;">');
var imgElem = angular.element('<img src="" width="50" style="margin-left:10px;visibility:hidden;">');
element.after(fileElem);
element.after(imgElem);console.log(scope.item); //This give me undefined
/*if(scope.item.url){
imgElem.css('visibility','visible');
imgElem[0].src = scope.item.url;
}*/
fileElem.on('change',function(e){
e.stopPropagation();
var files = e.target.files;
var reader = new FileReader();
reader.onloadend = function () {
var url = reader.result;
imgElem.css('visibility','visible');
imgElem[0].src = url;
scope.$apply(function () {
scope.item.url = url;
});
}
reader.readAsDataURL(files[0]);
});
element.on('click', function(e) {
e.stopPropagation();
fileElem[0].click();
});
element.on('$destroy',function(){
element.off('click');
});
fileElem.on('$destroy',function(){
fileElem.off('change');
});
}
},
};
});
Why console.log(scope.item); give me undefined
but I can see the right values fill the form ?
and how can I get the value ?
(btw I've tried also with $timeout or $apply but both doesn't work)
I've also tried with
scope.$watch('item', function(newVal, oldVal){
console.log(newVal, oldVal);
}, true);
but I've got
[Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"
and I don't really understand why
console.log(scope.item);// Object { $$conf={...}, $id="-J_C-q-6bIW9PBZzqpAg"
console.log(angular.equals({}, scope.item));// but this is true !
Ugly ends up
//controller
$scope.item = item;
$scope.item.$loaded().then(function(data) {
$scope.item = data;
});
//directive
if(scope.item.$id){
scope.item.$loaded().then(function(data) {
imgElem.css('visibility','visible');
imgElem[0].src = data.url;
});
if anyone have got a better solution is welcome :)
}

Firebase angularfire child.$asObject give properties undefined

I've got this code:
factory
app.factory('Items', function($firebase,FIREBASE_URL) {
var ref = new Firebase(FIREBASE_URL);
var items = $firebase(ref.child('items')).$asArray();
var Item = {
all: function () {
return items;
},
create: function (item) {
return items.$add(item);
},
get: function (itemId) {
return $firebase(ref.child('items').child(itemId)).$asObject();
},
update: function (itemId, item) {
return $firebase(ref.child('items').child(itemId)).update(item);
},
delete: function (item) {
return items.$remove(item);
}
};
return Item;
});
route
app.config(function($stateProvider) {
$stateProvider
.state('items_update', {
url: '/items/update/:id',
templateUrl: 'views/items/form.html',
controller:'ItemsUpdateController',
resolve:{
item:function(Items,$stateParams){
return Items.get($stateParams.id);
}
}
})
});
controller
app.controller('ItemsUpdateController', function ($scope, item, $state) {
$scope.item = item;
console.log($scope.item.url);
$scope.add = function() {
Items.update($scope.item).then(function () {
$state.transitionTo('items');
});
}
});
why console.log($scope.item.url); give me undefined ?
but in the view I've got all the data
html
<form class="form-horizontal" role="form" name="form" data-ng-submit="add()">
<div class="form-group">
<input type="text" name="title" tabindex="1" class="form-control" placeholder="{{ 'items.form.title' | translate }}" data-ng-model="item.title" required="required" data-ng-minlength="3" data-ng-maxlength="25" user-feedback />
</div>
<div class="form-group">
<input type="text" name="ingredients" tabindex="2" class="form-control" placeholder="{{ 'items.form.ingredients' | translate }}" data-ng-model="item.ingredients" required="required" ng-pattern="/^\w(\s*,?\s*\w)*$/" user-feedback />
</div>
<div class="form-group">
<input type="text" name="price" tabindex="3" class="form-control" placeholder="{{ 'items.form.price' | translate }}" data-ng-model="item.price" required="required" data-smart-float user-feedback />
</div>
<div class="form-group">
<button type="button" tabindex="4" class="btn btn-default btn-lg" item="item" data-uploader>{{ 'items.form.upload' | translate }}</button>
<input type="text" name="url" style="display:none;" required="required" data-ng-model="item.url" />
</div>
<div class="form-group form-no-required clearfix">
<div class="pull-right">
<button type="submit" tabindex="5" class="btn btn-primary" data-ng-disabled="form.$invalid">{{ 'items.form.submit' | translate }}</button>
</div>
</div>
</form>
ENDS UP
as in the #Frank van Puffelen comment
I worked it out with:
app.controller('ItemsUpdateController', function($scope, item, $state) {
item.$loaded().then(function(data) {
$scope.item = data;
console.log($scope.item.url);
});
$scope.add = function() {
Items.update($scope.item).then(function() {
$state.transitionTo('items');
});
}
});
This is because by the time your console.log($scope.item.url); runs, the data hasn't been loaded from Firebase yet. Angular listens for a notification from Firebase/AngularFire to know when the data has loaded and then updates the view.
Also see angularfire - why can't I loop over array returned by $asArray? and Trying to get child records from Firebase.

Resources