I made a json file designer for PDF generating.
If you want to see the whole code in action open the plunker link at the bottom.
The view doesnt behave as expected. In debugger the model changes immediately when i drag the element in its SVG scene. The input doesnt change though. BUT if i click between the input boxes it suddenly updates the view to the correct values.
This is where I set the values in the scope variable inside a directive:
function endDrag(evt) {
if (selectedElement) {
let selectedEntry = scope.data.templateData.find(function(entry) {
return entry.name === selectedElement.getAttribute("data-entry-name");
});
if(selectedEntry){
selectedEntry.x = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.e / scope.data.pdfViwer.zoom);
selectedEntry.y = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.f / scope.data.pdfViwer.zoom);
}
selectedElement = null;
}
}
This is my data object in the controller:
$scope.data = {
name: "",
type: [{name:'Text',value:'text'}, {name:'Image',value:'image'}, {name:'Line',value:'line'}],
templateData: [{
'type': {name:'Text',value:'text'},
'name': 'test',
'text': 'test3',
'x': 100,
'y': 100
}],
pdfViwer: {
height: 2970,
width: 2000,
zoom: .3
},
output: {
show:true
}
}
Those are the input fields that update too late:
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">(X,Y)</span>
</div>
<input type="text" ng-model="entry.x" aria-label="x" ng-init="entry.x=data.pdfViwer.width / 2" class="form-control">
<input type="text" ng-model="entry.y" aria-label="y" ng-init="entry.y=data.pdfViwer.height / 2" class="form-control">
</div>
This is the group tag for the svg groups in the Preview SVG:
<g ng-repeat="entry in getTemplateData()" class="draggable" data-entry-name="{{entry.name}}"
transform="translate({{entry.x * data.pdfViwer.zoom}} {{entry.y * data.pdfViwer.zoom}})"
draggable="true">
The fact that it updates the input fields at a later point shows visibly that the data is transfered correctly to the controller. Why does the Form on the right side update so lazy. Is their no way to force the view to rerender?
Thank you very much in advance for every helpful advise :/
I made a json file designer for PDF generating.
If you want to see the whole code in action open the plunker link at the bottom.
The view doesnt behave as expected. In debugger the model changes immediately when i drag the element in its SVG scene. The input doesnt change though. BUT if i click between the input boxes it suddenly updates the view to the correct values.
This is where I set the values in the scope variable inside a directive:
function endDrag(evt) {
if (selectedElement) {
let selectedEntry = scope.data.templateData.find(function(entry) {
return entry.name === selectedElement.getAttribute("data-entry-name");
});
if(selectedEntry){
selectedEntry.x = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.e / scope.data.pdfViwer.zoom);
selectedEntry.y = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.f / scope.data.pdfViwer.zoom);
}
selectedElement = null;
}
}
This is my data object in the controller:
$scope.data = {
name: "",
type: [{name:'Text',value:'text'}, {name:'Image',value:'image'}, {name:'Line',value:'line'}],
templateData: [{
'type': {name:'Text',value:'text'},
'name': 'test',
'text': 'test3',
'x': 100,
'y': 100
}],
pdfViwer: {
height: 2970,
width: 2000,
zoom: .3
},
output: {
show:true
}
}
Those are the input fields that update too late:
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">(X,Y)</span>
</div>
<input type="text" ng-model="entry.x" aria-label="x" ng-init="entry.x=data.pdfViwer.width / 2" class="form-control">
<input type="text" ng-model="entry.y" aria-label="y" ng-init="entry.y=data.pdfViwer.height / 2" class="form-control">
</div>
This is the group tag for the svg groups in the Preview SVG:
<g ng-repeat="entry in getTemplateData()" class="draggable" data-entry-name="{{entry.name}}"
transform="translate({{entry.x * data.pdfViwer.zoom}} {{entry.y * data.pdfViwer.zoom}})"
draggable="true">
The fact that it updates the input fields at a later point shows visibly that the data is transfered correctly to the controller. Why does the Form on the right side update so lazy. Is their no way to force the view to rerender?
Thank you very much in advance for every helpful advise :/
https://plnkr.co/edit/UwbxV6eQ7YBWEtZAFkCj?p=preview
Share Improve this question asked Aug 7, 2019 at 18:25 code1x1.decode1x1.de 3042 silver badges13 bronze badges1 Answer
Reset to default 7You can force the view to render with $scope.$apply()
$apply() is used to execute an expression in AngularJS from outside of the AngularJS framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the AngularJS framework we need to perform proper scope life cycle of exception handling, executing watches.
https://docs.angularjs/api/ng/type/$rootScope.Scope#$apply
There is also an $applyAsyc()
method as well:
Schedule the invocation of $apply to occur at a later time. The actual time difference varies across browsers, but is typically around ~10 milliseconds. This can be used to queue up multiple expressions which need to be evaluated in the same digest.
https://docs.angularjs/api/ng/type/$rootScope.Scope#$applyAsync
I played around with your plnker and it looks like if you put scope.$apply();
at the end of your endDrag()
function it then works as intended:
function endDrag(evt) {
if (selectedElement) {
let selectedEntry = scope.data.templateData.find(function(entry) {
return entry.name === selectedElement.getAttribute("data-entry-name");
});
if(selectedEntry){
selectedEntry.x = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.e / scope.data.pdfViwer.zoom);
selectedEntry.y = parseInt(selectedElement.transform.baseVal.getItem(0).matrix.f / scope.data.pdfViwer.zoom);
}
selectedElement = null;
}
scope.$apply();
}
The reason for this is that it appears as if your drag events aren't tied in to Angular's digest cycle, so you need to invoke it manually for Angular to act on the change.