Ok, so i built a little app to exercise what i've learned so far with vue, but theres some things that i want to do but have no idea HOW yet
<div class="container" id="app">
<div class="row">
<div class="col-xs-6 jumbotron">
<form class="form-horizontal" #submit.prevent>
<p>
<label>Name</label>
<input id="inputName" type="text" class="form-control" v-model="dataToArray.name">
</p>
<p>
<label>Sex</label>
<input type="radio" name="sex" value="male" v-model="dataToArray.sex"> Male
<input type="radio" name="sex" value="female" v-model="dataToArray.sex"> Female
</p>
<p>
<label>Select a Color</label>
<select id="selectColor" class="form-control" v-model="dataToArray.color">
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
</p>
<p>
<button class="btn btn-primary" #click="addToArray()">Add to Array</button>
</p>
</form>
</div>
<div class="col-xs-6">
<table id="table" class="table table-bordered" v-if="savedData.length > 0">
<thead>
<th>Name</th>
<th>Sex</th>
<th>Color</th>
<th></th>
</thead>
<tbody id="test">
<tr v-for="(data, index) in savedData" v-if="savedData[index].status">
<td>{{ data.name }}</td>
<td>{{ data.sex }}</td>
<td>{{ data.color }}</td>
<td class="text-center">
<button #click="editThis(index)" class="btn btn-warning">Edit</button>
<button #click="saveEdit(index)" class="btn btn-default">Save</button>
<button class="btn btn-danger" #click="deleteThis(index)">Delete</button>
</td>
</tr>
</tbody>
</table>
{{ dataToArray.id }} <br>
{{ dataToArray.name }} <br>
{{ dataToArray.sex }} <br>
{{ dataToArray.color }} <br>
{{ savedData }}
</div>
</div>
</div>
new Vue({
el: '#app',
data:{
dataToArray: {
id: null,
name: '',
sex: '',
color: '',
status: true
},
savedData: []
},
methods: {
addToArray(){
this.dataToArray.id = this.savedData.lenth;
this.savedData.push(Object.assign({}, this.dataToArray));
},
deleteThis(index){
this.savedData[index].status = false;
},
editThis(index, event){
document.getElementById("inputName").value = this.savedData[index].name;
document.getElementById("selectColor").value = this.savedData[index].color;
//check the form radio according to the current sex of the object
},
saveEdit(index){
this.savedData[index].name = document.getElementById("inputName").value;
this.savedData[index].color = document.getElementById("selectColor").value;
//this.savedData[index].sex = get the new radio value
}
}
});
This is the app:https://jsfiddle.net/myrgato/10uqa1e1/5/
The edit and save button, i wanted to hide the edit button and show the saved button when the edit button is clicked, and the otherway around when the save button is clicked.
Editing the sex value of the object, i cant get the new radio value (the checked one after i click edit and select a new one)
Hiding the table if there are no rows, i am able to do that at the first time by comparing it to the size of the looping array, but when i delete rows, i dont delete the objects from the array, i just change the status, so if add one object to the array and delete it, the row will be gone (shows only if status = true) but the table will not (because even tho there are no rows, the object still exists inside the array)
Can someone help me understand how to achieve this?
Edit: Updated the code with what we got so far:
https://jsfiddle.net/myrgato/rcj3kef7/
As you can see, if i add two items to the table, and edit ONE, all the rows show the save button, how can i only show the save button of the row that i clicked?
and another one, check the following code: https://jsfiddle.net/myrgato/rcj3kef7/1/
In this one, i put the save button outside the table, in the form itself, so when the user clicks edit on a row, the save button and the current values show on the form.
The problem is, how will i get the index thats inside the v-for to my saveThis function that is outside?
You want to have an editing mode. When you're in editing mode, the Save button appears and the Edit button disappears; otherwise, the reverse. That's just a variable that you set to the index of the row being edited, or null when not editing.
For copying values between dataToArray and savedData, Object.assign is handy.
Since you want to hide the table when it's empty and it's empty when there are no items with a true status member, create a computed that uses find to tell you if there are any such items.
new Vue({
el: '#app',
data: {
dataToArray: {
id: null,
name: '',
sex: '',
color: '',
status: true
},
savedData: [],
editing: false
},
computed: {
hasVisibleData() {
return this.savedData.find(d => d.status);
}
},
methods: {
addToArray() {
this.dataToArray.id = this.savedData.lenth;
this.savedData.push(Object.assign({}, this.dataToArray));
},
deleteThis(index) {
this.savedData[index].status = false;
},
editThis(index, event) {
this.editing = index;
Object.assign(this.dataToArray, this.savedData[index]);
},
saveEdit(index) {
this.editing = null;
Object.assign(this.savedData[index], this.dataToArray);
}
}
});
.jumbotron {
background-color: ;
}
label {
color: ;
}
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div class="container" id="app">
<div class="row">
<div class="col-xs-6 jumbotron">
<form class="form-horizontal" #submit.prevent>
<p>
<label>Name</label>
<input id="inputName" type="text" class="form-control" v-model="dataToArray.name">
</p>
<p>
<label>Sex</label>
<input type="radio" name="sex" value="male" v-model="dataToArray.sex"> Male
<input type="radio" name="sex" value="female" v-model="dataToArray.sex"> Female
</p>
<p>
<label>Select a Color</label>
<select id="selectColor" class="form-control" v-model="dataToArray.color">
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
</p>
<p>
<button class="btn btn-primary" #click="addToArray()">Add to Array</button>
</p>
</form>
</div>
<div class="col-xs-6">
<table id="table" class="table table-bordered" v-if="hasVisibleData">
<thead>
<th>Name</th>
<th>Sex</th>
<th>Color</th>
<th></th>
</thead>
<tbody id="test">
<tr v-for="(data, index) in savedData" v-if="savedData[index].status">
<td>{{ data.name }}</td>
<td>{{ data.sex }}</td>
<td>{{ data.color }}</td>
<td class="text-center">
<button v-if="editing!==index" #click="editThis(index)" class="btn btn-warning">Edit</button>
<button v-if="editing===index" #click="saveEdit(index)" class="btn btn-default">Save</button>
<button class="btn btn-danger" #click="deleteThis(index)">Delete</button>
</td>
</tr>
</tbody>
</table>
{{ dataToArray.id }} <br> {{ dataToArray.name }} <br> {{ dataToArray.sex }} <br> {{ dataToArray.color }} <br> {{ savedData }}
</div>
</div>
</div>
You would want to set a flag when one or the other is clicked that way you can change both accordingly.
new Vue ({
data: {
edit:[] //0 means that neither button is clicked.
},
methods:{
editThis(index, event){
this.edit[index] = 1;
this.dataToArray.name = this.savedData[index].name;
this.dataToArray.color = this.savedData[index].color;
this.dataToArray.color = this.saveData[index].sex;
},
saveEdit(index){
this.edit[index] = -1
this.savedData[index].name = this.dataToArray.name
this.savedData[index].color = this.dataToArray.color
this.savedData[index].sex = this.dataToArray.sex
//since we have bound the dataToArray values with v-model we can modify them from here.
},
addToArray(index){
this.dataToArray.id = this.savedData.lenth;
this.edit[index] = 0;
this.savedData.push(Object.assign({}, this.dataToArray));
},
})
Then in your template you want to have a "v-if" property to show and hide based on the value of the flag.
<button #click="editThis(index)" v-if="edit[index] && edit[index] > -1" class="btn btn-warning">Edit</button>
<button #click="saveEdit(index)" v-if='edit[index] && edit[index] < 1' class="btn btn-default">Save</button>
Also, in order to hide the table when there is no data you also have to use a v-if on the table itself. You can also do a computed that returns the number of elements in the array that return a status that is not equal to false like so.
new Vue({
computed:{
elements(){//using the ES6 arrow function syntax and Array.reduce
return this.savedData.reduce((accum, iter) => {
if(iter.status != false) accum += 1
}, 0);
}
}
})
Then in your template you can place your table element like so:
<table id="table" class="table table-bordered" v-if="elements">
Related
I am trying to use inifinite-scroll directive for angularJS. The examples show usage of div inside the div, but in my case I'm trying to use it in a table. Here is my html:
<div class="scrolling-table-body">
<table class="table table-bordered table-hover table-list">
<thead search-table-header data-table="duplicatesTable"
data-search="sort(column)"
data-show-row-selector="true"
data-hide-sorting-indicator="true"
data-row-selector-click="selectAllRows(allSelected)"
data-column="column">
</thead>
<tbody infinite-scroll="loadMore()">
<tr ng-repeat="row in duplicatesArray"
ng-click="selectedDuplicateIndex=$index;"
ng-class="{selected: $index === selectedDuplicateIndex}">
<td style="text-align:center;">
<input type="checkbox"
name="checkRow"
ng-model="row.isSelected"
ng-change="selectRow(row, $index);" />
</td>
<td>
<span ng-if="row.barcode>0">{{row.barcode}}</span>
<span>{{$index}}</span>
<span class="pull-right">
<i class="fa fa-trash"
style="color:red;"
ng-click="removeRow($index)"
title="#Labels.delete"></i>
</span>
</td>
<td>
<div class="col-xs-12">
<input type="text"
name="assetNo"
id="assetNo"
ng-model="row.assetNo"
class="form-control"
ng-change="checkAssetNo(row)"
ng-maxlength="100"
sm-duplicate-validator
validate-duplicates="true"
error-message="row.errorMessage"
api-method="api/rentalEquipments/checkForDuplicate"
primary-key-value="row.equipmentId"
ng-model-options="{ debounce: { default : 500, blur: 0 }}" />
</div>
</td>
<td>
<input type="text"
name="serialNo1"
id="serialNo1"
ng-model="row.serialNo1"
class="form-control"
ng-maxlength="100" />
</td>
The above is used inside the modal form (bootstrap modal).
I initially load 10 rows into my duplicatesArray and I have the following code for loadMore function:
$scope.loadMore = function () {
const last = $scope.duplicatesArray.length;
if (last < $scope.numberOfDuplicates) {
for (let i = 1; i <= 10; i++) {
self.logInfo("Loading more duplicates...");
const newEquipment = {
equipmentId: (last + i) * -1,
descrip: self.model.descrip,
homeShopId: self.model.homeShopId,
ruleId: self.model.ruleId,
manufacturerId: self.model.manufacturerId,
modelId: self.model.modelId,
typeId: self.model.typeId,
levelId: self.model.levelId,
equipSize: self.model.equipSize,
bootMm: self.model.bootMm,
bindingManufacturerId: self.model.bindingManufacturerId,
bindingModelId: self.model.bindingModelId,
cost: self.model.cost,
bindingCost: self.model.bindingCost,
unitCost: self.model.unitCost,
errorMessage: "",
duplicateForm: true,
duplicatedId: self.model.equipmentId,
isDuplicate: true,
barcode: 0,
assetNo: "",
serialNo1: "", serialNo2: "", serialNo3: "", serialNo4: "",
isSelected: false
};
$scope.duplicatesArray.push(newEquipment);
}
}
};
There is currently an issue in this js code (I moved check for last < numberOfDuplicates before the loop thinking it may be the issue).
When I open my modal I see 20 items in the list and when I scroll I don't see more items.
Do you see what am I doing wrong?
Also, does it matter that I have the following markup for the modal:
<ng-form name="equipmentDuplicatesForm">
<div class="modal-body">
<div id="fixed-header-table">
<div class="fixed-header-bg">
</div>
<div class="scrolling-table-body">
table goes here
</div>
<div class="modal-footer hundred-percent padTop padBottom">
<button type="button" class="btn btn-warning"
data-dismiss="modal" aria-hidden="true"
ng-click="$dismiss()">
#Labels.cancel
</button>
</div>
</ng-form>
I click on the edit button for a special row in my table to grab that JSON object id on that row. Then I send back all the data related to that row id to my form inputs to edit and update that object again in db.Json. By clicking on btn_insert it will trigger the addToJsonDb function, but nothing will happen, and my json object does not become updated in db.json.
I do not have any problem to insert a new JSON object to the users JSON array DB and I do it every time by generating a new unique id with Math for that new JSON object to add. My problem is to update a JSON object as I explained above.
Users.vue
<template>
<!-- <textarea class="tinymce tiny"></textarea> -->
<div class="container fluid">
<form class="form1" style="border: solid 1px" >
<div class="form-group">
<!-- style="visibility: hidden;" -->
<input disabled type="text" class="form-control" id="id" placeholder="Id" v-model="usersArray.id" required>
</div>
<div class="form-group">
<label>Ad Soyad</label>
<input type="text" class="form-control" id="name" placeholder="Name" v-model="usersArray.name" required>
</div>
<div class="form-group">
<label>kullanci Adi</label>
<input type="text" class="form-control" id="userName" placeholder="userName" v-model="usersArray.username" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" id="password" placeholder="Password" v-model="usersArray.password" required>
</div>
<label for="custom-select" class="label">Select State</label>
<select class="custom-select" v-model="usersArray.state" required>
<option value="Active" selected>Active</option>
<option value="Passive">Passive</option>
</select>
<br><br>
<button id="btn_insert" type="submit" class="btn btn-primary" v-on:click.prevent="addToJsonDb"><i class="fas fa-plus-circle"></i>Add To Json DB</button>
</form>
<br><br>
<!-- npm install -g json-server -->
<!-- json-server --watch db.json -->
<h1 class="text-center">User Table</h1>
<table id="tbl_user" class="table table-bordered table-dark table-hover">
<thead>
<tr>
<!-- <th >id</th> -->
<th>name</th>
<th>username</th>
<th>password</th>
<th>State</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr v-for="item in this.tr_items">
<td>{{ item.name }}</td>
<td>{{ item.username }}</td>
<td>{{ item.password }}</td>
<td>{{ item.state}}</td>
<td><button type="submit" class="btn btn-danger btn-block" v-on:click.prevent="editThis(item)">Edit</button></td>
</tr>
</tbody>
</table>
<br>
</div>
</template>
<script>
export default {
data () {
return {
usersArray: [{
id: 0,
name: '',
username: '',
password: '',
state:''
}],
tr_items: [],
}
},
methods:{
addToJsonDb:function() {
if (this.usersArray.id == null)
{
var secret_id = Math.random().toString(20).substr(5,10);
}
else
{
secret_id = this.usersArray.id;
console.log("this id " + secret_id + " should replace with new data in json database");
}
this.usersArray.id = secret_id;
//push new inserted data from model=our form fields into tr_items
this.tr_items.push(this.usersArray);
this.$http.post('http://localhost:3000/users', {
id: secret_id,
name:this.usersArray.name,
username:this.usersArray.username,
password:this.usersArray.password,
state:this.usersArray.state,
}).then(function(data)
{
console.log(data);
});
this.usersArray.id = '';
},
getdata:function(){
var self = this;
$.getJSON('http://localhost:3000/users',function(data){
console.log(data);
for(var i in data) {
self.tr_items.push(data[i]);
}
});
},
editThis:function(data){
console.log(data.id);
var selected_user = null;
for(var i in this.tr_items)
{
if(this.tr_items[i].id == data.id )
{
selected_user = this.tr_items[i];
break;
}
}
if(selected_user != null) {
this.usersArray.id = selected_user.id;
this.usersArray.name = selected_user.name;
this.usersArray.username = selected_user.username;
this.usersArray.password = selected_user.password;
this.usersArray.state = selected_user.state;
}
else
{
console.error(data.id + " not found in the list");
}
}
},
mounted(){
this.getdata();
},
}
</script>
<style lang="scss" scoped>
.form1{
padding: 3vw;
}
</style>
First, I made a file with the name db.json in my project folder, then I wrote my JSON users array in it. Second, I installed a virtual json server with npm install -g json-server, then I executed it with json-server --watch db.json to watch my json.db.
db.json
{
"users": [
{
"id": "15759ig248",
"name": "asdsad",
"username": "reza_attitudead",
"password": "123",
"state": "Passive"
},
{
"id": "9036956e1j",
"name": "engin",
"username": "engin",
"password": "321",
"state": "Active"
}
]
I'm building a pizza menu app in Vue.js. If a user buys 3 of the same size pizza, then I need to display the toppings they want to add for each pizza.
The problem is when I click on a checkbox for pizza-3, it jumps up a checks that topping on pizza-1.
For some reason, I can't get the set of toppings (checkboxes), independent of one another. I'm having trouble figuring this one out. Please help.
<div v-for="n in Number(quantity)">
<button class="btn btn-primary" type="button" data-toggle="collapse"
:data-target="'#collapse' +n" aria-expanded="false" aria-
controls="collapseExample">
Add Toppings for <b>Pizza - {{n}}</b>
</button>
<div class="collapse.show" :id="'#collapse' +n">
<div class="card card-body">
<div class="row">
<div v-for="category in categories" class="col">
<table>
<tr>
<th><h4><b>{{category.name}}</b></h4></th>
</tr>
<tr v-for="name in category.topping_items">
<td>
<input type="checkbox" v-model="selected" :value="name.item
+ '-pizza-' + n " :id="name.id + n" />
<label :class="{bold_name: name.double_price}"
:for="name.id + n">{{name.item}}</label>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="align-content-center">
<button #click="closeForm">Add Selected Toppings</button>
</div>
<script>
export default {
name: "AddToppings",
props:['item', 'quantity'],
data(){
return{
selected:[]
}
},
created(){
},
computed:{
categories(){
return this.$store.state.cat_toppings;
}
},
methods:{
cancelCatDelete(){
$('#addToppings').modal('hide')
},
closeForm(){
//console.log('cart', this.item);
$('#addToppings').modal('hide');
this.item.toppings.push(this.selected);
this.$store.dispatch('addItemToCart', this.item);
this.selected = [];
this.$emit('form_closed');
}
}
}
I've updated your code.
Here are the major things that changed:
The selected data property is changed to object so that it can handle multiple arrays of selected toppings based on the category.
A watcher for the categories is added which will react everytime the category is changed. So for example, if you added a new category into your store, the selected data property will add new array entries for each new category that was added.
We used this.$set() to add new entry to your selected object. This is crucial for keeping everything reactive, specially to object properties or arrays that are dynamically added.
We updated the v-model mapping for the checkbox into v-model="selected[category.name]"
Lastly, we can now loop the selected to retrieve the selected toppings for each category
like this:
this.selected.forEach((selected, category_name) => {
this.item.toppings.push(selected);
});
See the fully updated code below:
export default {
name: "AddToppings",
props: ['item', 'quantity'],
data() {
return {
selected: {}
}
},
created() {
},
computed: {
categories() {
return this.$store.state.cat_toppings;
}
},
watch: {
categories: {
immediate: true,
handler(categories) {
categories.forEach((category) => {
if (this.selected[category.name] == undefined) {
this.$set(this.selected, category.name, []);
}
})
}
}
},
methods: {
cancelCatDelete() {
$('#addToppings').modal('hide')
},
closeForm() {
//console.log('cart', this.item);
$('#addToppings').modal('hide');
this.selected.forEach((selected, category_name) => {
this.item.toppings.push(selected);
});
this.$store.dispatch('addItemToCart', this.item);
this.selected = [];
this.$emit('form_closed');
}
}
}
<div v-for="n in Number(quantity)">
<button class="btn btn-primary" type="button" data-toggle="collapse" :data-target="'#collapse' +n" aria-expanded="false" aria- controls="collapseExample">
Add Toppings for <b>Pizza - {{n}}</b>
</button>
<div class="collapse.show" :id="'#collapse' +n">
<div class="card card-body">
<div class="row">
<div v-for="category in categories" class="col">
<table>
<tr>
<th>
<h4><b>{{category.name}}</b></h4>
</th>
</tr>
<tr v-for="name in category.topping_items">
<td>
<input type="checkbox" v-model="selected[category.name]" :value="name.item
+ '-pizza-' + n " :id="name.id + n" />
<label :class="{bold_name: name.double_price}" :for="name.id + n">{{name.item}}</label>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="align-content-center">
<button #click="closeForm">Add Selected Toppings</button>
</div>
What am I doing wrong here. Need help.
When I click on "Add" button, the data I selected in the rows of table are becoming blank. But When I select Delete button and then click on Add button, then it not emptying of one time only. If I see console, I can see data there, but it is not showing up on the screen.
Here is my code:
html:
<div class="container">
<div class="row" style="margin-bottom: 10px;">
<div class="col">
<div class="row111">
<label for="Select Image" class="col-sm-311 col-form-label111">Add Threshold and Notification for this Inspection: </label>
<div class="col-sm-9">
</div>
</div>
</div>
<div class="col">
<div class="float-right">
<button class="btn btn-default" type="button" (click)="addNotification()">Add</button>
</div>
</div>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>#</th>
<th>Threshold</th>
<th>Notification Level</th>
<th>Message</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- <tr> -->
<tr *ngFor="let notification of notificationArray; let i = index">
<td>{{i+1}}</td>
<td>
<select class="form-control" maxlength="50" readonly
required
id="threshold"
name="notification.thresholdId"
[(ngModel)]="notification.thresholdId"
#threshold="ngModel" >
<option value="0" selected> Select </option>
<option *ngFor="let threshold of thresholdList" value="{{threshold.thresholdId}}" >
{{threshold.threshold}}
</option>
</select>
</td>
<td>
<input [(ngModel)]="notification.notificationLevel" required class="form-control" type="text" name="notification.notificationLevel" />
</td>
<td>
<input [(ngModel)]="notification.message" required class="form-control" type="text" name="notification.message" />
</td>
<td>
<button class="btn btn-default" type="button" (click)="deleteNotification(i)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
component.ts:
notificationArray: Array<NotificationLevel> = [];
newNotification: any = {};
ngOnInit(): void {
this.newNotification = {thresholdId: "0", notificationLevel: "", message: ""};
this.notificationArray.push(this.newNotification);
}
addNotification(index) {
this.newNotification = {thresholdId: "0", notificationLevel: "", message: ""};
this.notificationArray.push(this.newNotification);
console.log(this.notificationArray); // I can see all entered data in console
return true;
}
deleteNotification(index) {
if(this.notificationArray.length ==1) {
alert("At least one Notification Required for an Inspection");
return false;
} else {
this.notificationArray.splice(index, 1);
return true;
}
}
Ok, solve the problem:-
The main problem is in name="" attribute. name="" must differ in each row .We can solve it in two ways:
1) Either Change the name="" attributes name dynamically so that for every row it has a different name, i did it to add index number with it as
<input [(ngModel)]="notification.notificationLevel" name="notificationThreshold{{i}}" required class="form-control" type="text" />
2) Or avoid name="" and so We can avoid [(ngModel)] By [value] and (input) and can use as like :-
<input [value]="notification.notificationLevel" (input)="notification.notificationLevel=$event.target.value" required class="form-control" type="text"/>
In fact, all of your notificationArray elements is the same instance of newNotification. By doing this : this.newNotification = {thresholdId: "0", notificationLevel: "", message: ""}; you actually reset the first line too because of it.
Try to store newNotification in a var instead :
notificationArray: Array<NotificationLevel> = [];
newNotification: any = {};
ngOnInit(): void {
var newNotification = {thresholdId: "0", notificationLevel: "", message: ""};
this.notificationArray.push(newNotification);
}
addNotification(index) {
console.log(this.notificationArray);
// here is the correction
var newNotification = {thresholdId: "0", notificationLevel: "", message: ""};
this.notificationArray.push(newNotification);
console.log(this.notificationArray);
return true;
}
deleteNotification(index) {
if(this.notificationArray.length ==1) {
alert("At least one Notification Required for an Inspection");
return false;
} else {
this.notificationArray.splice(index, 1);
return true;
}
}
update :
I don't know if it's related but you'll have duplicate threshold id on your select. Use your i to make it unique.
It's the same for your input names. You should add [] after the field name otherwise only the last row will be submit.
I added a console.log of you array after the push. Can you tell in comment if the first index is reset at this point ?
Of course the row is cleared because you are clearing it:
this.newNotification = {thresholdId: "0", notificationLevel: "", message: ""};
So on clicking the add button, the bound values are overridden and then you are pushing it into the array. Thus they are cleared :)
I am following an AngularJS tutorial, and I wanted to validate my form. I decided to add a default option to the select element.
However, even after adding selected="", the browser won't show it as default.
I have tried this without AngularJS and it works fine, so I'm guessing the script is blocking something.
How can I define a default option for my select element?
PS: I'm using Google Chrome Version 44.0.2403.157 m
var controllers = angular.module('formsApp.Controllers', []);
controllers.controller('todoCtrl', function($scope) {
$scope.todoList = [{
action: 'Get groceries',
complete: false
}, {
action: 'Call plumber',
complete: false
}, {
action: 'Buy running shoes',
complete: true
}, {
action: 'Buy flowers',
complete: false
}, {
action: 'Call family',
complete: false
}];
$scope.addNewItem = function(newItem) {
$scope.todoList.push({
action: newItem.action + ' (' + newItem.location + ')',
complete: false
});
};
});
var app = angular.module('formsApp', ['formsApp.Controllers']);
form input.ng-invalid.ng-dirty {
background-color: lightpink;
}
<!DOCTYPE html>
<html data-ng-app="formsApp">
<head>
<title>Forms</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body>
<div id="todoPanel" class="panel" data-ng-controller="todoCtrl">
<h3 class="panel-header">
To Do List
<span class="label label-info">
{{(todoList | filter: {complete: false}).length }}
</span>
</h3>
<div class="row">
<div class="col-xs-4">
<div class="well">
<form name="todoForm" novalidate data-ng-submit="addNewItem(newTodo)">
<div class="form-group row">
<label for="actionText">Action:</label>
<input type="text" id="actionText" class="form-control" data-ng-model="newTodo.action" required="" />
</div>
<div class="form-group row">
<label for="actionLocation">Location:</label>
<select id="actionLocation" class="form-control" data-ng-model="newTodo.location" required="">
<option selected="">Home</option>
<option>Office</option>
<option>Mall</option>
</select>
</div>
<button type="submit" class="btn btn-primary btn-block" data-ng-disabled="todoForm.$invalid">
Add
</button>
</form>
</div>
</div>
<div class="col-xs-8">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Action</th>
<th>Done</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="item in todoList">
<td>
{{$index + 1}}
</td>
<td>
{{item.action}}
</td>
<td>
<input type="checkbox" data-ng-model="item.complete" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
From the dev guide for ngSelected;
The HTML specification does not require browsers to preserve the
values of boolean attributes such as selected. (Their presence means
true and their absence means false.) If we put an Angular
interpolation expression into such an attribute then the binding
information would be lost when the browser removes the attribute. The
ngSelected directive solves this problem for the selected attribute.
This complementary directive is not removed by the browser and so
provides a permanent reliable place to store the binding information.
In your controller add another property and reference it from there:
{
action: 'Call family',
complete: false,
selected: 'selected'
}];
{
action: 'Call family',
complete: false,
selected: ''
}];