Ответ 1
ng-repeat
создает дочернюю область для каждой строки (для каждого equipment
). Таким образом, область EditRowController
является дочернимScope родительского quoteBuckingRaterController
.
Этот childScope содержит:
- все свойства родительской области (например,
equipment
,makes
,models
) - свойство
equip
с одним значением массиваequipment
, предоставленным ng-repeat - любое дополнительное свойство области, которое определено внутри блока ng-repeat, например.
rowform
Поэтому вы можете получить доступ к этим свойствам в childController EditRowController
с помощью переменной $scope, например:
$scope.equip.make
$scope.equipment
и внутри элемента ng-repeat
в html файле с помощью выражения angular, например:
{{equip.make}}
{{equipment}}
Теперь $scope.$watch
: если вы предоставили строку в качестве первого аргумента, это выражение angular, как в html файле, без окружающих скобок {{}}
. Пример для equip.make
:
$scope.$watch('equip.make', function (value) {
console.log('equip.make value (on save): ' + value);
});
Однако angular -xeditable обновляет значение equip.make только тогда, когда пользователь сохраняет строку. Если вы хотите смотреть пользовательский вход вживую, вы должны использовать свойство $data в объекте rowform, предоставляемое angular -xeditable:
$scope.$watch('rowform.$data.make', function (value) {
console.log('equip.make value (live): ' + value);
}, true);
Вы также можете использовать ng-change:
<span editable-select="equip.make" e-name="make" e-ng-change="onMakeValueChange($data)" e-form="rowform" e-ng-options="s.value as s.name for s in makes">
JS:
$scope.onMakeValueChange = function(newValue) {
console.log('equip.make value onChange: ' + newValue);
}
Это должно решить ваш первый вопрос: как посмотреть свойство make
.
Второй вопрос, как определить, когда строка редактируется, а когда нет, может быть решена с помощью атрибутов onshow/onhide в форме или путем просмотра свойства $visible объекта rowform
в области видимости как задокументированный в angular -используемой ссылке
<form editable-form name="rowform" onshow="setEditable(true)" onhide="setEditable(false)">
$scope.setEditable = function(value) {
console.log('is editable? ' + value);
};
// or
$scope.$watch('rowform.$visible', function(value) {
console.log('is editable? ' + value);
});
Вы можете спросить, почему объект rowform находится в текущем childScope.
Он создается тегом <form>
. См. ссылку angular о встроенной директиве формы:
Директива, которая создает экземпляр FormController.
Если указан атрибут name, публикуется контроллер формы на текущую область под этим именем.
Рабочий фрагмент с кодом примера:
angular.module('app', ["xeditable"]);
angular.module('app').controller("editRowController", function ($scope) {
$scope.testClick = function () {
alert('button clicked');
};
$scope.$watch('equip.make', function (value) {
console.log('equip.make value (after save): ' + value);
});
$scope.$watch('rowform.$data.make', function (value) {
console.log('equip.make value (live): ' + value);
}, true);
// detect if row is editable by using onshow / onhide on form element
$scope.setEditable = function(value) {
console.log('is equip id ' + $scope.equip.id + ' editable? [using onshow / onhide] ' + value);
};
// detect if row is editable by using a watcher on the form property $visible
$scope.$watch('rowform.$visible', function(value) {
console.log('is equip id ' + $scope.equip.id + ' editable [by watching form property]? ' + value);
});
});
angular.module('app').controller("quoteBuckingRaterController", function ($scope, $filter) {
$scope.equipment = [];
$scope.makes = [{value: 1, name: 'Horst'}, {value: 2, name: 'Fritz'}];
$scope.models = [{id: 1, name: 'PC', make: 1}];
$scope.showModel = function(equip) {
if(equip.model) {
var selected = $filter('filter')($scope.models, {id: equip.model});
return selected.length ? selected[0].name : 'Not set';
} else {
return 'Not set';
}
};
$scope.showMake = function(equip) {
if (equip.model) {
var selected = $filter('filter')($scope.models, { id: equip.model });
if (selected.length && selected.length > 0) {
if (equip.make != selected[0].make)
equip.make = selected[0].make;
return selected[0].make;
}
else {
return 'Not set';
}
} else {
return 'Not set';
}
};
$scope.checkName = function (data, id) {
if (!data) {
return "Description is required";
}
};
$scope.checkModel = function (data, id) {
if (!data) {
return "Model is required";
}
};
$scope.saveEquipment = function (data, id) {
$scope.inserted = null;
};
$scope.cancelRowEdit = function (data, id) {
$scope.inserted = null;
};
$scope.removeEquipment = function(index) {
$scope.equipment.splice(index, 1);
};
$scope.addEquipment = function() {
$scope.inserted = {
id: $scope.equipment.length+1,
name: '',
make: null,
model: null
};
$scope.equipment.push($scope.inserted);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-xeditable/0.1.9/js/xeditable.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/angular-xeditable/0.1.9/css/xeditable.css" rel="stylesheet"/>
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div ng-app="app" ng-controller="quoteBuckingRaterController">
<div class="col-md-12" style="margin-bottom: 3px">
<div class="col-md-4 col-md-offset-1" style="padding-top: 6px; padding-left: 0px"><label>Equipment</label></div>
<div class="col-md-offset-10">
<button class="btn btn-primary btn-sm" ng-click="addEquipment()">Add row</button>
</div>
</div>
<div class="col-md-10 col-md-offset-1">
<table class="table table-bordered table-hover table-condensed">
<tr style="font-weight: bold; background-color: lightblue">
<td style="width:35%">Name</td>
<td style="width:20%">Make</td>
<td style="width:20%">Model</td>
<td style="width:25%">Edit</td>
</tr>
<tr ng-repeat="equip in equipment" ng-controller="editRowController">
<td>
<!-- editable equip name (text with validation) -->
<span editable-text="equip.name" e-name="name" e-form="rowform" onbeforesave="checkName($data, equip.id)" e-required>
{{ equip.name || 'empty' }}
</span>
</td>
<td>
<!-- editable make (select-local) -->
<span editable-select="equip.make" e-name="make" e-form="rowform" e-ng-options="s.value as s.name for s in makes">
{{ showMake(equip) }}
</span>
</td>
<td>
<!-- editable model (select-remote) -->
<span editable-select="equip.model" e-name="model" e-form="rowform" e-ng-options="g.id as g.name for g in models" onbeforesave="checkModel($data, equip.id)" e-required>
{{ showModel(equip) }}
</span>
<button type="button" ng-disabled="rowform.$waiting" ng-click="testClick()" class="btn btn-default">
test
</button>
</td>
<td style="white-space: nowrap">
<!-- form -->
<form editable-form name="rowform" onbeforesave="saveEquipment($data, equip.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == equip" onshow="setEditable(true)" onhide="setEditable(false)">
<button type="submit" ng-disabled="rowform.$waiting" class="btn btn-primary">
save
</button>
<button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" class="btn btn-default">
cancel
</button>
</form>
<div class="buttons" ng-show="!rowform.$visible">
<button class="btn btn-primary" ng-click="rowform.$show()">edit</button>
<button class="btn btn-danger" ng-click="removeEquipment($index)">del</button>
</div>
</td>
</tr>
</table>
</div>
</div>