Multiple checkbox-forms with ng-repeat - angularjs

I'm new to angularjs / ionic and I try to create an ionic-app that posts IDs of prodcuts to a webserver. I have to display multiple <form> on one page with checkboxes (..and other types like select).
When I submit the first form everything works as expected. But when I try to submit a second form, the scope contains values from the first and from the second form. When i submit an empty form it also submits the values from the first form. Is there a way to "clean" the scope after every submit? How can I assure that the submit-button only submits values from its own form?
This is the <form> :
<form ng-submit="addCartFive()" name="type5_{{item.ID}}">
<div class="row">
<div class="col col-80"><strong>{{item['name']}}</strong> <br/>
{{item['description']}}
</div>
</div>
<div ng-repeat="variant in item.variants">
<ion-list ng-repeat="detail in variant.details">
<ion-checkbox name="sub-{{$index}}" ng-true-value="{{detail.ID}}" ng-model="formDataObjFive[$index][detail.ID]">
{{detail.name}} <span class="right">+ {{detail.price}}</span>
</ion-checkbox>
</ion-list>
</div>
<div class="row">
<button type="submit" ng-click="setValueFive(formDataObjFive)">order</button>
</div>
</form>
this is the relevant part of my controller:
$scope.setValueFive = function(a1) {
$scope.formDataObjFive = a1;
};
$scope.addCartFive = function () {
console.log($scope.formDataObjFive);
CartService.save($scope.formDataObjFive) // send the values to factory wich posts to server
};

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>

Validate form using dynamically textarea name

I have one validation form using angular. I would like validate forms in ng-repeat using dynamically textarea name. Look on my code:
<div ng-repeat="comment in comments track by $index">
<form name="main.adminArticleReplyForm" novalidate>
<div ng-class="{'has-success':(main.adminArticleReplyForm.commentReply_{{$index}}.$valid), 'has-error':(!main.adminArticleReplyForm.commentReply_{{$index}}.$valid)}">
<textarea name="commentReply_{{$index}}" ng-model="main.commentReply[$index]" required></textarea>
<ul ng-show="(!main.adminArticleReplyForm.commentReply_{{comment.number}}.$pristine && main.adminArticleReplyForm.$error.minlength[0].$viewValue.length)">
<li>You have to add {{10 - main.adminArticleReplyForm.$error.minlength[0].$viewValue.length}} characters</li>
</ul>
<button type="submit">Submit</button>
</div>
</form>
</div>
And my problems:
If you check {{main.adminArticleReplyForm}} commentReply_{{$index}} is always last $index in ng-repeat for example if are 4 comments in array in form always is commentReply_4, but textareas name in DOM are correct.
I have to use controller as, in my case main, but if I remove main from form name, everything works nice.
Summary, {{main.adminArticleReplyForm}} is validate only for last $index in ng-repeat previously $indexes are ignored
Here is fiddle for look that every commentReply_{{$index}} is commentReply_2 https://jsfiddle.net/8od25zhb/5/
Description
you don't need to track it by index that make repeat last index
you don't need to add main to the form, because form is in repeat so make it unique, if you want to have just one form make it out of repeat; so we just use comment.adminArticleReplyForm as form name, and just main.comments used main from controller.
by this 2 step your forms validate just the textarea which inside it.
you don't need create unique names and models for textarea, because you create them inside ng-repeat and all are unique.
<div ng-app="app" ng-controller="ctrl as main">
<div ng-repeat="comment in main.comments">
<form name="comment.adminArticleReplyForm" novalidate>
{{comment.adminArticleReplyForm}}
<div>
<textarea name="commentReply" ng-model="comment.commentReply" required></textarea>
<button type="submit">Submit</button>
</div>
</form>
<hr/>
</div>
</div>
Since, AngularJS default validation works on hierarchy of element names to detect their state thus, the name of textarea you have used is commentReply_{{$index}} with a underscore but you are using commentReply{{comment.number}} in the validation expressions. So make it look with a underscore and it will work. So, final code will look something like this:
<div ng-repeat="comment in comments track by $index">
<form name="main.adminArticleReplyForm" novalidate>
<div ng-class="{'has-success':(main.adminArticleReplyForm.commentReply_{{$index}}.$valid), 'has-error':(!main.adminArticleReplyForm.commentReply_{{$index}}.$valid)}">
<textarea name="commentReply_{{$index}}" ng-model="main.commentReply[$index]" required></textarea>
<ul ng-show="(!main.adminArticleReplyForm.commentReply_{{comment.number}}.$pristine && main.adminArticleReplyForm.$error.minlength[0].$viewValue.length)">
<li>You have to add {{10 - main.adminArticleReplyForm.$error.minlength[0].$viewValue.length}} characters</li>
</ul>
<button type="submit">Submit</button>
</div>
</form>
</div>

How do you create a dynamic select list from comma separated string?

I am taking information from my database and trying to figure the best way to display it within the app.
This is my database info
[{"form_input_id":"1","form_id":"6","title":"Please enter your room number?","input_type":"text","identifer":"room","choices":"s:0:\"\";","heading":"Valet Request"},{"form_input_id":"2","form_id":"6","title":"Please enter any comments or feedback.","input_type":"textarea","identifer":"feedback","choices":"s:0:\"\";","heading":"Valet Request"},{"form_input_id":"3","form_id":"6","title":"Please choose office","input_type":"select","identifer":"office","choices":"s:19:\"Sales, Reservations\";","heading":"Valet Request"},{"form_input_id":"18","form_id":"6","title":"Last Name","input_type":"text","identifer":"Last_Name","choices":"s:0:\"\";","heading":"Valet Request"},{"form_input_id":"19","form_id":"6","title":"Type of Car","input_type":"select","identifer":"Car_type","choices":"s:20:\"Buick, Olds, Ferrari\";","heading":"Valet Request"}]
I am able to pull everything the way I want to except choices. I am trying to create dynamic forms and need to create a select showing the choices.
My current controller:
controller('FormCtrl', function($scope, $ionicLoading){
// Grab Form
var form = angular.fromJson(window.localStorage.getItem('form'));
// Set Title
$scope.title = form[0].heading;
// Send Form Data
$scope.forms = form;
})
And my view:
<ion-view title="Form" hide-nav-bar="true">
<ion-header-bar align-title="left" class="bar-dark">
<div class="buttons">
Cancel
</div>
</ion-header-bar>
<ion-content id="dynamic" scroll="true" padding="true">
<h2 class="text-center">{{title}}</h2>
<form>
<div ng-repeat="form in forms">
<label>{{form.title}}</label>
<div ng-if="form.input_type == 'text'">
<input type="text" name="{{form.identifier}}" />
</div>
<div ng-if="form.input_type == 'time'">
<input type="time" name="{{form.identifier}}" />
</div>
<div ng-if="form.input_type == 'textarea'">
<textarea name="{{form.identifier}}"></textarea>
</div>
<div ng-if="form.input_type == 'select'">
<select name="{{form.identifier}}">
NEED TO FIGURE HOW TO DISPLAY CHOICES AS OPTIONS
</select>
</div>
</div>
</form>
</ion-content>
You need to parse your options from string. Something like that:
angular.forEach($scope.forms, function(item){
item.options=item.choices.split('"')[1].split(',');
});
And tnen use ng-options in select:
<select name="{{form.identifier}}" ng-options="choice for choice in form.options" ng-model="Your model here"></select>
https://docs.angularjs.org/api/ng/directive/ngOptions

How to relate view and controller when user can add input field?

This is my HTML code in angular template. In my controller I have
$scope.contacts.
Every contact in $scope.contacts can have multiple contact.fields. You can see I have 2 ng-repeat here, for every contact and every contact.field. User can add contact manually, and for every contact it is defined how many fields it has. So user click on plus and contact with empty fields is added. My question is: how to bind view with $scope.contacts, so when user adds new contact, it shows up in $scope.contacts?
<div id="contactsContainer">
<div id="{{contact.divId}}" ng-style="{'border': contact.borderStyle}"
class="form-group {{contact.divId}}" ng-mouseover="hoverIn()"
ng-mouseleave="hoverOut()" ng-repeat="contact in contacts track by $index">
<label class="col-sm-3 control-label">{{ translate[contact.keyTranslationName]}}</label>
<div id="fieldContainer" class="col-sm-4">
<div id="currentField" class="row mb5"
ng-repeat="field in contact.field track by $index">
<div id="{{contact.idPersonContact}}"
class="{{field.width}} has-icon pull-left">
<input name="{{field.name}}"
id="{{field.id}}"
placeholder="{{ translate[field.keyTranslationPlaceholder] }}"
class="form-control" value="{{field.value}}"
style="background-image: url();background-position: left;background-repeat: no-repeat;background-size:20px;">
</div>
</div>
</div>
</div>
<input type="button" ng-click="addContact()" />
// Controller
$scope.addContact = function(){
$scope.contacts.push({field : []});
// or field : Array(defaultFieldSize)
$scope.contacts.push({field : new Array(5) }); // Contact with 5 empty fields
}
Adding a contact in the contacts collection would do it. So when the user creates the new contact using the button you would do something like:
var newContact = {
field1:'',
field2: ''
...
}
and then just add the new contact to the contacts collection.
$scope.contacts.push(newContact);
ng-repeat will detect the change in the collection and render it.

show a hidden element after user login with angularjs

Iam relatively new to angularjs and jquery mobile.I was asked to do research for my next project on these framework and so Iam trying to achieve certain functionalities.I have created a front page where an element is hidden,this page will be shown initially.Then clicking on login ,the user will be redirected to login page,where he provides username password to log in.Then he will be redirected to the same front page but i want the hidden element to be visible.Can you help me with this.My element is always hidden and I cant figure out what Iam doing wrong.The tag with hi welcome user text must be visible after log in
Here's my html front page
<div data-role="page" id="panel-responsive-page1" data-title="Panel responsive page" data-url="panel-responsive-page1">
<div role="main" class="ui-content">
/**some content **/
<div class="ui-grid-solo" ng-controller="LoginCtrl" >
<p ng-hide="userWelcome">Hi welcome User </p>
</div>
</div>
<div data-role="panel" id="nav-panel">
<ul data-role="listview">
<li>Login</li>
<li>Register</li>
</ul>
</div>
</div>
On clicking login,i will be redirected to login page
<div data-role="page" id="login-form">
<!-- header -->
<div data-role="header" class="backgroundColorPink">
<h1>Login Form</h1>
</div>
<!-- Form Content -->
<div role="main" class="ui-content jqm-content">
<form class="userform">
<h2>Login</h2>
<label for="name">Username:</label>
<input type="text" name="name" id="name" value="" data-clear-btn="true" data-mini="true" ng-model="userDetails.name">
<label for="password">Password:</label>
<input type="password" name="password" id="password" value="" data-clear-btn="true" autocomplete="off" data-mini="true" ng-model="userDetails.password">
<div class="ui-grid-a" ng-controller="LoginCtrl">
<div class="ui-block-a">Cancel</div>
<div class="ui-block-b ">Save</div>
</div>
</form>
</div>
</div>
On clicking save,i will isssue a Ajax call and on successful login i will be redirected to the front page,and my login element must be visible.
Hers my controller
angular.module('jQMDemo', [])
function LoginCtrl($scope,$http,$window) {
$scope.userWelcome=true;
$scope.userLogin = function() {
var data={username: $scope.userDetails.name, password: $scope.userDetails.password, callfrom: "Portal"} ;
$http.post('url',data).success(function(data,status) {
alert(data.status);
if(data.status=="success"){
$window.location.href='#panel-responsive-page1';
$scope.userWelcome=false;
}
});
}
}
I might be using the controller wrong or maybe wrong usage of ng-hide..Please help,I cant figure it out
<div ng-show="element.show">
<!--codes-->
</div>
This will show if the element exists in your controller else it
will stay hidden
You can use this, so when you click on the button if everything
is good and the user is logged u create the element and then let the
class controller do the work for you
I achieved the functionality using toggleclass
I added this code in the controller:
$(".userWelcome").toggleClass("show");
And this in my HTML
<div class="ui-grid-solo hide userWelcome backgroundColorPink " >
<p class="alignMiddle ">Hi welcome {{userDetails.name}} </p>
</div>
I was able to get the desired result.If anyone else have any other way to achieve this,Please suggest

Resources