angularfire using $loaded how to access data in a directive - angularjs

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 :)
}

Related

file upload with other form data getting file undefined angularjs

'use strict';
var app = angular.module('myApp', []);
app.directive('fileModel', ['$parse', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
modelSetter(scope, element.files[0]);
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
app.service('fileUpload', ['$http', function($http) {
this.uploadFileToUrl = function(data, file, uploadUrl) {
var fd = new FormData();
fd.append('name', data.name);
fd.append('phone', data.phone);
fd.append('experience', data.experience);
fd.append('email', data.email);
fd.append('position', data.position);
fd.append('resume', file);
var promise = $http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
});
promise.then(function(response) {
var request = response.data;
if (request.success == "true") {
alert("Thank you for getting in touch with Mohar");
var inst = $('[data-remodal-id=modal]').remodal();
inst.close();
$scope.userForm.$setPristine();
$scope.userForm.$setUntouched();
} else {
alert("Please try after sometime");
window.location.href = 'career.html';
}
});
}
}]);
app.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload) {
$scope.val1 = 'Sr. Python Developer';
$scope.val2 = 'Jr. Python Developer';
$scope.val3 = 'Sr. UI Developer';
$scope.val4 = 'Jr. UI developer';
$scope.val5 = 'Sr. Android Developer';
$scope.val6 = 'Jr. Android Developer';
$scope.val7 = 'Sr. Tester';
$scope.val8 = 'Jr. Tester';
$scope.val9 = 'Sr. Devops Engineer';
$scope.val10 = 'Graphic designer';
$scope.applyJob = function(val) {
$scope.name = '';
$scope.phone = '';
$scope.experience = '';
$scope.email = '';
$scope.position = val
console.log('clicked', $scope.position);
}
$scope.uploadFile = function() {
var data = {
'name': $scope.name,
'phone': $scope.phone,
'experience': $scope.experience,
'email': $scope.email,
'position': $scope.position
}
var file = $scope.myFile;
console.log('file is ', $scope.myFile)
var uploadUrl = "career.php";
fileUpload.uploadFileToUrl(data, file, uploadUrl);
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<form name="userForm" class="job-form" autocomplete="off">
<div class="row">
<div class="form-group">
<input type="text" class="form-control form-control-payment" ng-model="name" name="name" id="name" ng-pattern="/^[a-zA-Z ]*$/" ng-minlength="1" ng-maxlength="20" placeholder="Full Name" required />
<div ng-show="userForm.name.$dirty && userForm.name.$invalid || userForm.name.$touched">
<p ng-show="userForm.name.$error.required">Please enter name</p>
<p ng-show="userForm.name.$error.pattern">Please enter valid name</p>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control form-control-payment" ng-model="phone" name="phone" id="number" ng-pattern="/^[0-9]*$/" ng-minlength="10" ng-maxlength="10" placeholder="Phone Number" required />
<div ng-show="userForm.phone.$dirty && userForm.phone.$invalid || userForm.phone.$touched">
<p ng-show="userForm.phone.$error.required">Please enter contact number</p>
<p ng-show="userForm.phone.$error.minlength">Please enter minimum 10 digit</p>
<p ng-show="userForm.phone.$error.maxlength || userForm.phone.$error.pattern">Please enter valid contact number</p>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control form-control-payment" ng-model="experience" name="experience" id="experience" ng-pattern="/^[0-9]*$/" placeholder="Experience" required />
<div ng-show="userForm.experience.$dirty && userForm.experience.$invalid || userForm.experience.$touched">
<p ng-show="userForm.experience.$error.required">Please enter total experience</p>
<p ng-show="userForm.experience.$error.pattern">Please enter only numbers</p>
</div>
</div>
<div class="form-group">
<input type="email" class="form-control form-control-payment" name="email" ng-model="email" id="email" placeholder="E-mail" required />
<div ng-show="userForm.email.$dirty && userForm.email.$invalid || userForm.email.$touched">
<p ng-show="userForm.email.$error.required">Email is required.</p>
<p ng-show="userForm.email.$error.email">Invalid email address.</p>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control form-control-payment" id="position" ng-model="position" ng-readonly="true" placeholder="Position" required />
<!-- <input type="text" class="form-control" id="position" placeholder="e.g: UI DEVELOPER" required> -->
</div>
<div class="form-group">
<input type="file" class="form-control form-control-payment" fileModel="myFile" id="resume" required>
</div>
<button type="submit" class="btn btn-submit pull-right" ng-click="uploadFile()">Submit</button>
</div>
<!-- ng-disabled="userForm.$invalid" -->
</form>
</div>
hello, I am using angularjs for validation & HTTP call. I want to post a file with some other form data like name, email, phone, experience, position etc.when I click on submit button It send an empty file. I don't understand what is wrong with this code please help i am new to angularjs. thank you in advance.
In the fileModel directive, delete the erroneous line:
app.directive('fileModel', ['$parse', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
̶m̶o̶d̶e̶l̶S̶e̶t̶t̶e̶r̶(̶s̶c̶o̶p̶e̶,̶ ̶e̶l̶e̶m̶e̶n̶t̶.̶f̶i̶l̶e̶s̶[̶0̶]̶)̶;̶
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
In the template, instantiate the directive with kebab-case not camelCase:
<input type="file" class="form-control form-control-payment"
̶f̶i̶l̶e̶M̶o̶d̶e̶l̶=̶"̶m̶y̶F̶i̶l̶e̶"̶
file-model="myFile"
id="resume" required>
For more information, see AngularJS Developer Guide - Directive Normalization

unable to get data from html in angular js

in this code of HTML, we get input text value and send to the Angular controller
so they get to work as defined in code.
<div class="row" ng-controller="RegionController">
<div class="col-lg-12" >
<div class="hpanel">
<div class="panel-heading">
<!-- <div panel-tools></div> -->
<h2>Region Master Entry</h2>
</div>
<div class="panel-body">
<!--change form name,and submit controller name-->
<form role="form">
<div class="form-group">
<label class="col-sm-2 control-label">Region Name</label>
<div class="col-sm-10">
<input type="text" placeholder="please enter Region name" class="form-control m-b" required name="Region Name" ng-model="formRegionData.region_name" >
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Region Code</label>
<div class="col-sm-10">
<input type="text" placeholder="please enter Region code" class="form-control m-b" required name="Region Code" ng-model="formRegionData.region_code">
</div>
</div>
<div class="form-group">
<div class="col-sm-3">
<label>Active</label>
</div>
<div class="checkbox checkbox-success col-sm-9">
<input id="checkbox3" type="checkbox" checked="" ng-model="formRegionData.status">
<label for="checkbox3">
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-4"></div>
<div class="col-sm-8">
<button class="btn btn-sm btn-primary btn-xl text-right" type="submit" ng-click="createRegion()"><strong> Save Region </strong></button>
</div>
</div>
{{formRegionData | json}}
</form>
</div>
</div>
</div>
</div>
"{{formRegionData | json}}" this will return in HTML input text result of but not send data to the controller
in Controller the code is written as
.controller('RegionController', function( $scope , regionService) {
$scope.createRegion = function() {
debugger;
vm.processing = true;
vm.message = '';
console.log(formRegionData);
regionService.SaveRegion( formRegionData )
.then(function(data) {
debugger;
//console.log(data);
//.success(function(data) {
vm.processing = false;
vm.storyData = {};
vm.message = data.message;
});
}
})
and my service to work according to Controller
.factory('regionService',function($http ){
var regionFactory = {};
regionFactory.SaveRegion = function(formRegionData) {
debugger;
return $http.post('/api/region/', formRegionData);
}
return regionFactory;
});
You have missed $scope
$scope.createRegion = function() {
debugger;
$scope.processing = true;
$scope.message = '';
console.log($scope.formRegionData);
regionService.SaveRegion($scope.formRegionData )
.then(function(data) {
debugger;
//console.log(data);
//.success(function(data) {
$scope.processing = false;
$scope.storyData = {};
$scope.message = data.message;
});
}
})
and remove ng-click="createRegion()" in your button control and add this code in your form tag by ng-submit. like,
<form ng-submit="createRegion()" role="form">
You have missed of $scope in form region data
Here is the link Jsfiddle
JS
angular.module('myApp', ['ngStorage'])
.controller('RegionController', function($scope, regionService) {
var vm = this;
$scope.createRegion = function() {
debugger;
vm.processing = true;
vm.message = '';
regionService.SaveRegion($scope.formRegionData)
.then(function(data) {
debugger;
//console.log(data);
//.success(function(data) {
vm.processing = false;
vm.storyData = {};
vm.message = data.message;
});
}
}).factory('regionService', function($http) {
var regionFactory = {};
regionFactory.SaveRegion = function(formRegionData) {
debugger;
return $http.post('/api/region/', formRegionData);
}
return regionFactory;
});

Building dynamic angular forms with ngrepeat and ngform

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);
}
}
});

ng-model not updating inside Modal

ng-model which i am assigning is controller can be seen inside modal.But when i am updating the data inside the modal,the $scope variable is not updating.
Also dropdown is not working whose value i have defined in my controller.
Do i need to make changes in directive.
<div ng-controller="MainCtrl" class="container">
<h1>Modal example</h1>
<button ng-click="toggleModal()" class="btn btn-default">Open modal</button>
<modal title="Login form" visible="showModal">
<div>
<select ng-model="client" ng-change="changeClient()" ng-options="item in clientList">
<label for="email">Email address</label>
<input type="text" ng-model="email" id="email" placeholder="Enter email" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" placeholder="Password" />
</div>
<button type="submit" ng-click="buttonClicked()" class="btn btn-default">Submit</button>
</modal>
</div>
CONTROLLER CODE
var mymodal = angular.module('mymodal', []);
mymodal.controller('MainCtrl', function ($scope) {
$scope.email="hello#abc.com";
$scope.showModal = false;
$scope.toggleModal = function(){
$scope.showModal = !$scope.showModal;
};
$scope.buttonClicked=function(){
alert("hello1");
alert($scope.email);
alert($scope.client);
}
$scope.clientList=["300","600","900"]
$scope.client=$scope.clientList[0];
$scope.changeClient = function() {
selectedValue=$scope.client;
alert(selectedValue);
};
});
mymodal.directive('modal', function () {
return {
template: '<div class="modal fade">' +
'<div class="modal-dialog">' +
'<div class="modal-content">' +
'<div class="modal-header">' +
'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' +
'<h4 class="modal-title">{{ title }}</h4>' +
'</div>' +
'<div class="modal-body" ng-transclude></div>' +
'</div>' +
'</div>' +
'</div>',
restrict: 'E',
transclude: true,
replace:true,
scope:true,
link: function postLink(scope, element, attrs) {
scope.title = attrs.title;
scope.$watch(attrs.visible, function(value){
if(value == true)
$(element).modal('show');
else
$(element).modal('hide');
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
}
};
});
Have a Look-JsFiddle Link
you should use:
$parent.email
<input type="text" ng-model="$parent.email" id="email" placeholder="Enter email" />
fiddle
As huan feng said, you can use '$parent' because directive has it's own isolated scope. For your 'select' the simplest solution is to use something like that:
<select ng-model="$parent.client" ng-change="changeClient()" ng-options="item for item in clientList">
But, it could be better to use your model in a little bit different way. Create your 'clientInfo' object with email and clien as properties.
JS:
.controller('MainCtrl', function ($scope) {
$scope.clientInfo = {};
$scope.clientInfo.email="hello#abc.com";
$scope.showModal = false;
$scope.toggleModal = function(){
$scope.showModal = !$scope.showModal;
};
$scope.buttonClicked=function(){
alert("hello1");
alert($scope.clientInfo.email);
alert($scope.clientInfo.client);
}
$scope.clientList=["300","600","900"]
$scope.clientInfo.client = $scope.clientList[0];
$scope.changeClient = function() {
selectedValue=$scope.clientInfo.client;
alert(selectedValue);
};
});
And HTML:
<div ng-controller="MainCtrl" class="container">
<h1>Modal example</h1>
<button ng-click="toggleModal()" class="btn btn-default">Open modal</button>
<modal title="Login form" visible="showModal">
<div>
<select ng-model="clientInfo.client" ng-change="changeClient()" ng-options="item for item in clientList">
<label for="email">Email address</label>
<input type="text" ng-model="clientInfo.email" id="email" placeholder="Enter email" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" placeholder="Password" />
</div>
<button type="submit" ng-click="buttonClicked()" class="btn btn-default">Submit</button>
</modal>
</div>

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