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: ''
}];
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'm a rookie on vue.js and I'm trying to extend some tutorials a completed.
Been fighting with this three hours now and I'm frustrated. FYI, I'm using firebase but I'm not sure it really matters here.
So, I have a CRUD app for listing movies (I told you it was basic!).
There is a form at the top of the page where you can add movies, and a table below it, where the new registries are listed. This works well.
I added Edit and Delete buttons to each row on the table. The delete function works. But the Edit function is the problem.
I'd like to use v-if on the initial form, to trigger different methods (save, edit) and show different buttons (Add, Save, Cancel).
I'm not sure how to access the objects to do this, I tried a couple of things and the v-if says the object is not defined.
thank you for reading, please ask anything you need.
import './firebase' // this has my credententials and initializeApp
import Vue from 'vue'
import App from './App'
import VueFire from 'vuefire'
Vue.use(VueFire)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
<template>
<div id="app" class="container">
<div class="page-header">
<h1>Vue Movies</h1>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3>Add Movie</h3>
</div>
<div class="panel-body">
<div v-if="!isEditing">
<form id="form" class="form-inline" v-on:submit.prevent="addMovie">
<div class="form-group">
<label for="movieTitle">Title:</label>
<input type="text" id="movieTitle" class="form-control" v-model="newMovie.title">
</div>
<div class="form-group">
<label for="movieDirector">Director:</label>
<input type="text" id="movieDirector" class="form-control" v-model="newMovie.director">
</div>
<div class="form-group">
<label for="movieUrl">URL:</label>
<input type="text" id="movieUrl" class="form-control" v-model="newMovie.url">
</div>
<input type="submit" class="btn btn-primary" value="Add Movie">
</form>
</div>
<div v-else>
<form id="form" class="form-inline" v-on:submit.prevent="saveEdit(movie)">
<div class="form-group">
<label for="movieTitle">Title:</label>
<input type="text" id="movieTitle" class="form-control" v-model="movie.title">
</div>
<div class="form-group">
<label for="movieDirector">Director:</label>
<input type="text" id="movieDirector" class="form-control" v-model="movie.director">
</div>
<div class="form-group">
<label for="movieUrl">URL:</label>
<input type="text" id="movieUrl" class="form-control" v-model="movie.url">
</div>
<input type="submit" class="btn btn-primary" value="Save">
<button v-on:click="cancelEdit(movie['.key'])">Cancel</button>
</form>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3>Movies List</h3>
</div>
<div class="panel-body">
<table class="table table-stripped">
<thead>
<tr>
<th>Title</th>
<th>director</th>
</tr>
</thead>
<tbody>
<tr v-for="movie in movies">
<td>
<a v-bind:href="movie.url" v-bind:key="movie['.key']" target="_blank">{{movie.title}}</a>
</td>
<td>
{{movie.director}}
</td>
<td>
<button v-on:click="editMovie(movie)">Edit</button>
</td>
<td>
<button v-on:click="removeMovie(movie)">Remove</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
import { moviesRef } from './firebase'
export default {
name: 'app',
firebase: {
movies: moviesRef
},
data () {
return {
isEditing: false, // maybe this helps?
newMovie: {
title: '',
director: '',
url: 'http://',
edit: false // or maybe this??
}
}
},
methods: {
addMovie: function() {
moviesRef.push( this.newMovie )
this.newMovie.title = '',
this.newMovie.director = '',
this.newMovie.url = 'http://'
this.newMovie.edit = false
},
editMovie: function (movie){
moviesRef.child(movie['.key']).update({ edit:true }); // can't access this one with v-if, not sure why
//this.newMovie = movie;
},
removeMovie: function (movie) {
moviesRef.child(movie['.key']).remove()
},
cancelEdit(key){
moviesRef.child(key).update({ edit:false })
},
saveEdit(movie){
const key = movie['key'];
moviesRef.child(key).set({
title : movie.title,
director : movie.director,
url : movie.url,
edit : movie.edit
})
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
You should change the isEditing to true when the Edit button clicked, and you should define the data movie.
editMovie: function (movie){
...
this.movie = Vue.util.extend({}, movie); // deep clone to prevent modify the original object
this.isEditing = true;
},
As suggested in the comments (by Ben), I added the movie declaration to the initial data object. So now it looks like this:
data () {
return {
isEditing: false,
newMovie: {
title: '',
director: '',
url: 'http://',
edit: false
},
movie: {
edit: false
}
}
},
Now v-if works just fine, like this:
<div v-if="!movie.edit">
"is Editing" was no longer necessary so I removed it.
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">
I am trying to use ng-hide to display the action of "Edit" button. For this, I am using a boolean "edit" in this way: "ng-model="edit" ng-value="true", but it has no effect and I can't figure it out why.
Here is my code:
<!DOCTYPE html>
<html >
<head>
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<meta charset="UTF-8">
<script src="../../../bower_components/angular/angular.js"></script>
<script src="app.js"></script>
<script src="categories/module/category-module.js"></script>
<script src="categories/controller/category-controller.js"></script>
<script src="categories/service/category-service.js"></script>
<title>Categories</title>
</head>
<body><div lang="en" ng-app="myCategories">
<div ng-controller="categoryController">
<div class="w3-container" ng-init='getCategories()'>
<h3>Categories</h3>
<table class="w3-table w3-bordered w3-striped">
<tr>
<th>Edit</th>
<th>Name</th>
<th>Description</th>
</tr>
<tr ng-repeat="category in categories">
<td>
<button class="w3-btn w3-ripple" ng-click="editCategory(category.id) " ng-model="edit" ng-value="true">✎ Edit</button>
</td>
<td>{{category.name }}</td>
<td>{{ category.description }}</td>
</tr>
</table>
<form ng-hide="edit">
<h3 ng-hide="edit">Edit Category:</h3>
<label> Name:</label>
<input class="w3-input w3-border" type="text" ng-model="name" ng-disabled="!edit" placeholder="{{category.name}}">
<br>
<label>Description:</label>
<input class="w3-input w3-border" type="text" ng-model="description" ng-disabled="!edit" placeholder="{{category.description}}">
<br>
<label>New Description:</label>
<input class="w3-input w3-border" type="text" ng-model="newDescription" placeholder="New Description">
<br>
<button class="w3-btn w3-green w3-ripple" ng-disabled="error || incomplete">✔ Save Changes</button>
</form>
</div>
</div>
</div>
</body>
</html>
//app.js
(function() {
var myComments = angular.module('myComments', [ 'comment' ]);
var myCategories = angular.module('myCategories', [ 'category' ]);
var myTopics = angular.module('myTopics', [ 'topic' ]);
})();
//category-controller
(function() {
'use strict';
angular.module('category').controller('categoryController',
topicControllerFunction);
topicControllerFunction.$inject = [ '$scope', 'categoryService' ];
function topicControllerFunction($scope, categoryService) {
$scope.getCategories = getCategories;
function getCategories() {
console.log();
$scope.categories=[];
var promise=categoryService.getCategories();
promise.then(function(data){
if(data!=undefined && data!=null){
$scope.categories=data;
} else{
$scope.categories=undefined;
}
},function(error){
console.log('error='+error);
$scope.categories=undefined;
})
categoryService.getCategories();
$scope.categories = categoryService.getCategories();
}
}
}())
Make sure edit is set to true in the case where you want to hide the desired section.
Inside editCategory() looks like a a good place for this to happen, instead of ng-value=true
Set $scope.edit = true; in editCategory()
Do something like:
<span ng-show = "edit == true">
I'm not sure if it can be done the way you're attempting (I've never used that technique, but here's how I'd do it:
<button ng-click="edit=!edit" ... ></button>
If you need edit to be true on load, you could either set it in your controller (best), or use ng-init:
<button ng-click="edit=!edit" ng-init="edit=true" ... ></button>
Also, you should have a dot in your ng-model value: If you are not using a .(dot) in your AngularJS models you are doing it wrong?
In my App I have an $http.get() request that stores data into the array $scope.requirements and a boolean into $scope.requirementsFulfilled.
I have a directive using the same controller as the page. They both do an ng-repeat on the $scope.requirements. When the requirementsFulfilled is false only the directive version shows, when true only the containing page.
The problem is when I envoke $http.get() after the first time the results are only being stored in the directive version. How do I make sure this information is bound to both?
Within the controller...
$scope.requirementsFulfilled;
$scope.requirements = [];
$scope.getRequirements = function(url) {
$http.get(url)
.then(function(res){
$scope.requirements = res.data.requirements;
$scope.setFulfilled( res.data.fulfilled );
});
};
$scope.submitRequirementScan = function() {
if ($scope.checkRequirement() ) {
$scope.getRequirements('tempjson/requiredPartsFulfilled.json');
}
};
$scope.setFulfilled = function( inputFulfilled ) {
$scope.requirementsFulfilled = inputFulfilled;
};
$scope.getRequirements('tempjson/requiredParts.json');
The page gets the requirements and populates the page. Then the user takes actions which fires off checkRequirement() and then fetches the new json if true. From this point only the directive is updating.
I believe that a child scope is being created for the directive, but I am not certain exactly what is happening. Here is the entirity of the directive info.
.directive("operationRequirements", function () {
return {
restrict: "E",
templateUrl: "requirements/requirements.html"
};
});
What is going on with it?
edit - Html for the directive
<div class="col-md-6 col-md-offset-3">
<h5>Scan Requirements</h5>
<form ng-submit="submitRequirementScan()" ng-controller="operationCtrl">
<label> <div class="glyphicon glyphicon-barcode ng-hide" ng-hide="requirement.scanned"></div>
<input type="text" ng-model="text" name="text" placeholder="Scan Barcode" autofocus /></label>
<input type="submit" id="submit" value="Submit Scan" class="btn" />
<table class="table table-hover">
<tr ng-repeat="requirement in requirements | filter : unScannedFilter">
<td>{{$index + 1 }}</td>
<td>
<div class="glyphicon glyphicon-barcode ng-hide" ng-hide="requirement.scanned"></div>
<div class="glyphicon glyphicon-check ng-show" ng-show="requirement.scanned"></div>{{requirement.scanned}}
<div class="col-md-4">
<input type="checkbox" ng-model="requirement.scanned">
</div>
</td>
<td>{{requirement.partId}} - {{requirement.partDescription}}</td>
</tr>
</table>
</form>
</div>
edit 2 -- Html that invokes the directive operation-Requirements and the on page display of the requirements hidden with ng-show.
<div class="row" ng-hide="requirementsFulfilled" >
<operation-Requirements></operation-Requirements>
</div>
<div class="col-md-12" ng-show="requirementsFulfilled">
<table class="table table-hover">
<tr ng-repeat="requirement in requirements">
<td>{{$index + 1 }}</td>
<td>
<div class="glyphicon glyphicon-barcode ng-hide" ng-hide="requirement.scanned"></div>
<div class="glyphicon glyphicon-check ng-show" ng-show="requirement.scanned"></div>
</td>
<td>{{requirement.partId}} - {{requirement.partDescription}}</td>
</tr>
</table>
</div>
So maybe this will help point you in the right direction. What I've done is pulled out the requirements stuff into its own service. Now you have a singleton that handles everything that deals with parts. When its updated in one place its updated everywhere. The directive no longer needs that other controller.
http://plnkr.co/edit/Nej79OI3NrKcrkMNix3D?p=preview
app.service('partsService', function() {
return {
requirementsFulfilled: false,
requirements: [],
getRequirements: function () {
this.requirements.push({partId: 1, partDescription: 'Some Desc', scanned: false});
this.requirements.push({partId: 2, partDescription: 'Some Desc 2', scanned: true});
},
submitScan: function (id) {
this.requirements.filter(function (part) {
return part.partId === id;
}).map(function (part) {
part.scanned = true;
});
this.requirementsFulfilled = this.requirements.filter(function (part) { return !part.scanned }).length === 0;
}
};
});