Create Dynamic ng-models for firebase use | ionic | firebase | angularjs - angularjs

I'm trying to make an app where users can tag other registered users in a post.
So the idea is if the user creates a new post. there is an ng-repeat for all the users available and for each of them a checkbox is created.
After the users are checked they have to be stored with the post in firebase.
Now i cant seem to figure out how to dynamically add properties to my firebase push
<div class="list">
<label class="item item-input item-stacked-label">
<span class="input-label">Titel</span>
<input type="text" placeholder="Titel" ng-model="formData.title">
</label>
<label class="item item-input item-stacked-label">
<span class="input-label">Beschrijving</span>
<input type="text" placeholder="Kaarten voor... etc" ng-model="formData.description">
</label>
<label class="item item-input item-stacked-label">
<span class="input-label">Prijs</span>
<input type="text" placeholder=".-" ng-model="formData.price">
</label>
</div>
<ion-list ng-repeat="user in users">
<ion-checkbox ng-click="la()" ng-model="users[user.Username][user.id][user.voltooid == false]" >
</ion-checkbox>
</ion-list>
<div class="button" ng-click="test()">test</div>
The push code
$scope.formData = {};
$scope.test = function (){
console.log($scope.users);
console.log($scope.formData);
posts.push({
title: $scope.formData.title,
description: $scope.formData.description,
price: $scope.formData.price,
users: {
//dynamic data
}
});
}

I'm gonna give you an example how to retrieve and post dynamically your data.
Here is a factory to sync your data with a controller/ng-model, but you can include it in a controller.
.factory("Items", function($firebaseArray) {
var itemsRef = new Firebase("https://YOUR-FIREBASE/");
return $firebaseArray(itemsRef);
})
In your controller you retrieve your data in a scope
$scope.items = Items;
Then use the function of angularfire call $save that will update your data into your firebase.
$scope.la = function(){
$scope.items.$save($scope.users[user.name][check]);
}
Finally you can do something like that to retrieve and update your data
<ion-checkbox ng-click="la()" ng-model="users[user.name][check]">

Related

$broadcast is not working in Angularjs

I am using two controllers. When changes happen in one controllers it should get changed immediately in the other controller. I am using the $broadcast event to achive this.
My code:
My First controller
app.controller('configurationCtrl', function($scope, $http,Notification,$rootScope,$cookies) {
$scope.awssubmit=function(){
$scope.page_loader=true
$http.post("/insert_config_details",$scope.userdata).then(function(List){
if(List){
$scope.page_loader=false;
$cookies.put("bucket",$scope.userdata.bucket_name)
$scope.$broadcast('eventEmitedName', 'Some data');
Notification.success('<span class="glyphicon glyphicon-ok"></span> <strong>AWS Configuration details updated successfully.</strong>');
}
else{
$scope.page_loader=false;
Notification.error('<span class="glyphicon glyphicon-ok"></span> <strong>Error!!! Please try again later.</strong>');
}
$scope.awssave = false;
$scope.awstext=true;
})
}
});
My Second Controller:
app.controller('SidemenuController', function($scope, $http,$location,BucketService)
{
$scope.$on('eventEmitedName', function (event, data) {
console.log("Called"); //I am not getting this
value
console.log(data); // 'Some data' // I am not getting this
value
});
});
aws_submit() is called from my view and everything seems to work fine. But in SidemenuController I am not getting any data. Is there any mistake in my code?
Update:
My view :
<form id="awsform" method="post" name="awsform" class="form-horizontal" novalidate>
<div class="col-sm-6 four_module_config">
<div class="account_settings">
<div class="col-sm-12 heading_config" ng-hide="awssave">
<h4 class="sub_title col-sm-11" style="border-bottom:none">AWS S3 Configurations</h4>
<% if(valid_role[1]) { %>
<div class="action col-sm-1">
<span class="actico editrole" ng-click="editaws()">
<a href='javascript:void(0)' ></a>
</span>
</div>
<% } %>
</div>
<div class="col-sm-12 heading_config" ng-show="awssave">
<h4 class="sub_title col-sm-9" style="border-bottom:none">AWS S3 Configurations</h4>
<div class="action col-sm-3 close_config">
<button type="button" class="site_btn submit_btn save_config col-sm-2" id="submit" ng-show="awstest"
ng-click="verifyaws()">Test</button>
<button type="button" class="site_btn submit_btn save_config col-sm-2" id="submit" ng-show="submitawssave"
ng-click="awssubmit()">Submit</button>
<button type="button" class="site_btn submit_btn save_config col-sm-2" id="submit" ng-click="closeaws()">Cancel</button>
</div>
</div>
<div class="ipfield col-md-8 hint_txt_conf">
*Enter your AWS access Key, S3 Bucket name configured in your AWS Environment. Which is used to store your document in the
cloud.
</div>
<div class="ipfield first_ipfield">
<div class="col-md-8">
<label for="name" class="usrlabel">AWS access key <span class="mandat">*</span></label>
<input type="password" ng-disabled="awstext" ng-model="userdata.key" required name="key" class="txt_box" id="key" placeholder="Enter AWS access key">
<span toggle="#key" class="fa fa-fw fa-eye field_icon toggle-password"></span>
</div>
</div>
<div class="ipfield">
<div class="col-md-8">
<label for="name" class="usrlabel">AWS Secret Key <span class="mandat">*</span></label>
<input type="password" ng-disabled="awstext" ng-model="userdata.secretkey" required name="secretkey" class="txt_box" id="secretkey" placeholder="Enter AWS Secret Key">
<span toggle="#secretkey" class="fa fa-fw fa-eye field_icon toggle-password"></span>
</div>
</div>
<div class="ipfield">
<div class="col-md-8">
<label for="name" class="usrlabel">AWS Region Code <span class="mandat">*</span></label>
<input type="text" ng-disabled="awstext" ng-model="userdata.region" required name="region" class="txt_box" id="region" placeholder="Enter AWS Region Code">
</div>
</div>
<div class="ipfield">
<div class="col-md-8">
<label for="name" class="usrlabel">AWS Bucket Name <span class="mandat">*</span></label>
<input type="text" ng-disabled="awstext" ng-model="userdata.bucket_name" required name="bucket_name" class="txt_box" id="bucket"
placeholder="Enter AWS Bucket Name">
</div>
</div>
</div>
</div>
</form>
If you want to send data from one controller to another controller using $brodcast than use $rootscope.$broadcast
$rootScope.$broadcast('eventEmitedName', 'Some data');
Second Controller
app.controller('SidemenuController', function($scope, $http,$location,BucketService) {
$scope.$on('eventEmitedName', function (event, data) {
console.log("Called");
console.log(data); // 'Some data'
$scope.bucket = data;
});
});
Note: Do not use $rootscope.$on as listener because $rootscope
listener are not destroyed . Instead it will create listeners stack
If you want to call one controller event into another there are four methods available:
$rootScope.$broadcast() if your controller are not in a parent / child relation.
If your second controller (event fired here) is a parent you can use $scope.$broadcast();
If your second controller (event fired here) is a child you can use $scope.$emit();
The best way to solve this would be to use a service -> Example of using a service to share data between controllers.
Note: You need to destroy $rootScope.$on() listeners manually avoid stacking events. This Difference between $rootScope.$on vs $scope.$on and this Do you need to unbind $scope.$on in $scope $destroy event? will help you understand the basics of using events.
View
<div ng-controller="MyCtrl">
<button ng-click="broadcast()">
broadcast
</button>
</div>
<div ng-controller="MySecondCtrl">
{{ test }}
</div>
AngularJS application
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope, $rootScope) {
$scope.broadcast = function() {
$rootScope.$broadcast('test', 'testit');
}
});
myApp.controller('MySecondCtrl', function($scope, $rootScope) {
var registerScope = $rootScope.$on('test', function(test, args) {
console.log(args);
$scope.test = args;
});
// clean up, destroy event when controller get destroyed.
$scope.$on('$destroy', registerScope);
});
> demo fiddle

Angularjs multiple functions

I have 2 buttons:
One scans a QR code and returns the values which works.
Another on the same page that confirms the input values, but I cannot get the second function to fire.
I have 2 inputs, deviceid and companyid, and 2 buttons. The scan button, via ng-click, calls scanQR and the second button, also via ng-click, calls checkBlanks.
A confirm ID button calls a functions to firstly check for blanks then alert the user if the input data is missing. Once the 2 inputs have content it will save the data via the verifyDetails() call. But I cannot get the checkBlanks function to run.
HTML Code is:-
<ion-view title="Settings">
<ion-content padding="true" class="has-header">
<form class="list">
<label class="item item-input" name="deviceid">
<span class="input-label">Device ID</span>
<input type="text" placeholder="" ng-model="deviceid">
</label>
<label class="item item-input" name="companyid">
<span class="input-label">Company ID</span>
<input type="text" placeholder="" ng-model="companyid">
</label>
</form>
<button ng-click="scanQR()" class="button button-positive button-block">Scan QR to Configure</button>
<button ng-click="checkBlanks()" class="button button-positive button-block">Confirm ID</button>
<form class="list">
<ion-toggle toggle-class="toggle-positive" ng-checked="true">Vibrate</ion-toggle>
<ion-toggle toggle-class="toggle-positive">Light on Scan</ion-toggle>
<div style="text-align:center;" class="show-list-numbers-and-dots">
<p style="color:#000000;font-size:10px;">On Android devices set to off and use the volume controls to turn the flashlight on or off.</p>
</div>
<ion-radio ng-model="radioCheck" value="security">Security</ion-radio>
<ion-radio value="utilities">Utilities</ion-radio>
</form>
</ion-content>
</ion-view>
AngularJS is:-
function($scope, $stateParams) {
$scope.radioCheck = "security";
$scope.scanQR = function() {
cordova.plugins.barcodeScanner.scan(
function(result) {
var TagResponse = result.text;
var config = TagResponse.indexOf("Config:");
if (TagResponse !== '') {
if (config === 0) {
var ConfigVals = TagResponse.split(':');
$scope.deviceid = ConfigVals[1];
$scope.companyid = ConfigVals[2];
$scope.$apply();
}
}
});
};
$scope.checkBlanks = function() {
alert("Device ID" + $scope.deviceid);
console.log("Device ID" + $scope.device)
if ($scope.deviceid === '') {
alert("Please enter a device ID", Dismissed, "Error");
} else if ($scope.companyid === '') {
alert("Please enter a Company ID", Dismissed, "Error");
} else {
verifyDetails();
}
};
}
Any help appreciated, I'm very new to Angularjs and Ionic.

Ionic radio group not reflecting in model

So I'm loading a bunch of questions from an api, every question has its own set of answers.
Im unable to populate the ng-model for radio box to record the selected answer
html
<div class="list">
<div class="item item-text-wrap" ng-repeat="question in vm.questions track by $index">
<h2>{{question.text}}</h2>
<ion-list if="question.type='mcq'">
<ion-radio ng-model="vm.answers[$index].answer_text" ng-value="'{{option.text}}'" ng-repeat="option in question.options" name="vm.answers[$index].answer_text">{{option.text}}</ion-radio>
</ion-list>
<input type="text" ng-if="question.type=='simple'" ng-model="vm.answers[$index].answer_text" placeholder="{{question.text}}"/>
</div>
</div>
relevalnt code from the controller
vm.answers = [];
api.need_assesment_questions.query(
//on success
function success(response) {
vm.questions = response;
//populate answers
for (var i = 0; i < vm.questions.length; i++) {
vm.answers.push({ question_text: vm.questions[i].text, answer_text: '' });
}
},
//on error
function error(response) {
alert(response.message);
}
);
The issue im facing is that answers array always rewrites the first answer text
fiddle : http://jsfiddle.net/pn2qL/76/
You need to initialise the question index on top and use it in your model, because there is another ng-repeat which override the previous $index
Try this
<div class="list">
<div class="item item-text-wrap"
ng-repeat="question in vm.questions track by $index"
ng-init="qIndex = $index">
<h2>{{question.text}}</h2>
<ion-list if="question.type='mcq'">
<ion-radio ng-model="vm.answers[qIndex].answer_text" ng-value="option.text" ng-repeat="option in question.options" name="{{vm.answers[qIndex].answer_text}}">{{option.text}}</ion-radio>
</ion-list>
<input type="text" ng-if="question.type=='simple'" ng-model="vm.answers[$index].answer_text" placeholder="{{question.text}}" />
</div>
</div>
Working fiddle

Angularjs List/Detail Edit

I am writing a small AngularJS/Ionic/Cordova application where I have a list of contacts. When the user taps on a contact, I navigate to a new page where details about the contact are shown (first name, last name, phone number). Here, the user can update details about the contact, or delete the contact. The problem I have is when the user deletes the contact the list still shows the deleted item after navigating back.
Right now I am storing the list of contacts in localStorage, but I do plan on eventually persisting these values in SQLite and/or a web service.
I am using two controllers, two html templates, and a factory. Why is the first list not updating when I make changes to a detail item? I am very new to AngularJS so please bear with me.
List Controller
angular
.module('app')
.controller('contactListCtrl', ['$scope', 'Contacts',
function($scope, Contacts) {
$scope.contacts = Contacts.get();
}
])
List Template
<ion-content scroll="false" class="padding-horizontal" has-header="true">
<div class="row padding-vertical">
<div class="col col-center text-center">
<span class="small-text primary-text-color">Contact List</span>
</div>
</div>
<div class="row" >
<div class="col col-center">
<ul class="list">
<li class="item" ng-repeat="contact in contacts" ui-sref="contactListEdit({id: $index})">
{{contact.fName}} {{contact.lName}}
</li>
</ul>
</div>
</div>
</ion-content>
Detail Controller
angular
.module('app')
.controller('editContactCtrl', ['$scope', '$stateParams', 'Contacts',
function($scope, $stateParams, Contacts) {
var contactId = false;
if ($stateParams.id !== 'undefined') {
contactId = $stateParams.id;
}
$scope.contact = Contacts.get(contactId);
$scope.contactId = contactId;
$scope.delete = function(index) {
Contacts.removeContact(index);
window.history.back();
};
}
])
Detail Template
<ion-content scroll="false" class="padding-horizontal" has-header="true">
<div class="row padding-vertical">
<div class="col col-center text-center">
<span class="medium-text primary-text-color">Edit contact</span>
</div>
</div>
<div class="list">
<label class="item item-input">
<input type="text" placeholder="First Name" ng-model="contact.fName">
</label>
<label class="item item-input">
<input type="text" placeholder="Last Name" ng-model="contact.lName">
</label>
<label class="item item-input">
<input type="text" placeholder="Phone" ng-model="contact.mobile">
</label>
<label class="item item-input">
<input type="text" placeholder="Email" ng-model="contact.email">
</label>
<button ng-click="save()" class="button button-full button-positive">
Save
</button>
<button ng-click="delete(contactId)" class="button button-full button-assertive">
Delete
</button>
</div>
</ion-content>
Contacts Factory
angular
.module('app')
.factory('Contacts', ['$http',
function($http) {
return {
get: function(index) {
var contacts;
try {
contacts = JSON.parse(window.localStorage.getItem("contacts"));
if (index >= 0) {
return contacts[index];
}
return contacts;
} catch (e) {
console.log("error parsing json contacts");
return false;
}
},
removeContact: function (index) {
var contactList = this.get();
if (index !== -1) {
contactList.splice(index, 1);
}
console.log(contactList);
this.saveContacts(contactList);
},
setDefaultContacts: function() {
var self = this;
return $http.get('./mock_data/contacts.json').then(function(response) {
// contacts already exist, don't set.
if (window.localStorage.getItem("contacts")) {
return false;
} else {
self.saveContacts(response.data);
return true;
}
});
},
saveContacts: function(contactList) {
window.localStorage.setItem("contacts", JSON.stringify(contactList));
},
};
}
])
I think you will find that the contactListCtrl is not being setup again when you navigate back to it (after a delete). I believe this is because Ionic caches views for you.
What you need to do is listen to $ionicView.beforeEnter event and load your contacts list into your ContactListCtrl scope whenever you receive this event.
So.. Try adding something like this to your controller:
$scope.$on('$ionicView.beforeEnter', function() {
$scope.contacts = Contacts.get();
}
);
Check out: http://ionicframework.com/blog/navigating-the-changes/

Angular js Dynamic Input and show value

I want dynamic input in my form so that user can add many input as much he wants
Same time I want to display the value of it..
Example:
Suppose i have one input
Customer: <input type="text" ng-model="name"/> <!--first input>
<a>Add more</a>
I can easily get value for it
All customers <p ng-bind="name"></p>
BUT if users add one more customer name input, Then how can i show that value
Under "All customers tag"
All customers <p ng-bind="name"></p> // Customer1,Customer1 name here
Use an array of objects on scope in conjunction with a ng-repeat. The button will then add to the array.
View:
<p ng-repeat="item in array">Name: <input type="text" ng-model="item.name" ></p>
<button ng-click="add()">Add</button>
<p>All customers</p>
<p ng-repeat="item in array">{{item.name}}</p>
Js:
app.controller('MainCtrl', function($scope) {
$scope.array = [];
$scope.add = function () {
$scope.array.push({ name: ''});
}
$scope.add();
});
Plunkr
You have to create array.
In your controller
$scope.inputs = [];
$scope.add = function() {
$scope.inputs.push({value: ''});
}
$scope.add();
now in HTML
<div ng-repeat="input in inputs">
<input type="text" ng-model="input.value" />
</div>
<button ng-click="add()">Add</button>
This is raw concept of how that might be done.
Update
Added plunker example
http://plnkr.co/edit/bHLXCjsP46GiixysZZ83?p=preview

Resources