ng-img-crop is an awesome directive however I am having trouble adapting it to my scenario. My issue is that when a user has an image I would like to give them the option to resize the image if they would like to.
So here is the code I am attempting to use:
js:
vm.userImageOriginal = vm.editUser.image_pkey ? 'api/file/' + vm.editUser.image_pkey : null;
html:
<img-crop image="profileVM.userImageOriginal" result-image="profileVM.userImageNew"
area-type="square" result-image-size="300" on-change="profileVM.imageCropped = true;"></img-crop>
So I two issues:
1) I only want to upload the new image if the user has indeed changed the cropping. I tried setting a flag in on-change but it looks like on-change gets executed on initialization as well. Is there any way to know if the user has actually cropped?
2) Is there any way to set the position of the square/circle. In my scenario, if there is an existing user image, I would like to set the cropping square to the dimensions of the current image (i.e. the border of the image).
Thanks in advance.
Solved like this:
Add the following attribute to ng-img-crop directive in html:
on-load-done="profileVM.addCroppingWatcher()"
Here is the function:
function addCroppingWatcher(){
if (croppingWatcher)
return;
$window.setTimeout(function(){
croppingWatcher = $scope.$watch(
function(){ return vm.userImageNew; },
function(newVal, oldVal){
if (oldVal && oldVal != newVal) {
vm.imageCropped = true;
croppingWatcher();
}
}
);
}, 0);
}
Related
How i want to resize image inside WYSIWYG editor when user upload image? I manage to insert into editor but i cant resize the image.
Below is my code :
http://embed.plnkr.co/yxMbI54wYUlxu2hSpfw8/preview
Appreciate your advice.
You can catch clicks on images inserted to the textarea and prompt for new size. The code below is only conceptual:
$(textarea[0]).on("click", "img", function(){
var me = this,
size = prompt("Size: ", me.width + "x" + me.height);
if (size) {
scope.$apply(function(){
var [w,h] = size.split("x");
$(me).css({ width: w, height: h });
});
}
});
Insert this snippet into link function of the wysiwyg directive, insert an image and click on it.
Notice that you cannot use standard angular.element because it doesn't support selectors in the .on method, so you have to use ol'good jQuery instead.
plunker
i try to get the the value of number row selected, and print it in HTML using Angularjs, but no issue,
i have the count only when i clic in the grid column header.
The value of " selectedRowsCounter " is 0 in html, when i dosn't clic in the grid header
my code is like
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
};
$scope.gridOptions = {
rowData: null,
angularCompileRows: true,
onSelectionChanged: activeButtons,
}
there is a screenshot
i have open the same subject here
https://github.com/ceolter/ag-grid/issues/1023
i have added this line to activeButtons function and it work fine
$scope.gridOptions.api.refreshView();
i dont knew if there is a good solution, but that work for now
The problem seems to be with Angular being unaware of the $scope property change because ag-grid does not tell Angular that it has modified something in the $scope. Although it is difficult to tell if you don't show your view.
You can use onSelectionChanged the way you are using it to know how many rows have been selected, but you need to tell Angular that something has changed in its $scope by applying it.
Something like this:
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
window.setTimeout(function() {
this.$scope.$apply();
});
};
That way you can apply the $scope and the html view will reflect the changes.
Have little dilemma here. I'm building text editor in angular js. The problem that I have is, when user selects part of text within a paragraph or heading I need to change styling of that part of text to bold / italic etc.
So basically I need to wrap selected text in <strong></strong> or <em></em>.
Plunker
I have a directive
editorApp.directive('watchSelection', function() {
return function(scope, elem) {
elem.on('mouseup', function() {
scope.startPosition = elem[0].selectionStart;
scope.endPosition = elem[0].selectionEnd;
// scope.selected = elem[0].value.substring(start, end);
scope.$apply();
});
};
});
That gets text selection its startposition and endposition. On button click I need to wrap that selection in specific tags, which I'm hoping to accomplish with this function:
$scope.boldText = function(startPosition, endPosition) {
$scope.start = startPosition;
$scope.end = endPosition;
var htmlStart = angular.element('<strong>');
var htmlEnd = angular.element('</strong>');
$scope.start.append(htmlStart);
$scope.end.append(htmlEnd);
};
I relatively new to angular and I might have taken a bigger bite than I can handle :)
Issue is I can't get selection to wrap inside them tags.
You don't need to watch anything.
$scope.boldText = function() {
document.execCommand('bold');
};
This will bold the selected text.
I am using FabricJS with an AngularJS application. I am able to add text to a canvas and, using the kitchensink example located here, I can perform functions such as bold, italic, underline, etc.
However, the issue I have is how to change the font family, text align, font size, etc. since when I make a selection from a dropdown for font family, no changes occur... but it works in the Kitchensink example.
I am using the Kitchensink example as I need to not only add text, but edit it once it shows on the Canvas, and this appears to have what I need.
A button (which is working) has an HTML element such as:
<button class="btn btn-object-action" type="button" ng-class="{'btn-inverse': isBold()}" ng-click="toggleBold()">
Bold</button>
Which is backed up by the following in the Controller:
$scope.toggleBold = function () {
setActiveStyle('fontWeight',
getActiveStyle('fontWeight') === 'bold' ? '' : 'bold');
};
As I stated, this works as intended. Where I am having challenges is changing something like the Font Family or Font Size in that the change is achieved without a button click. Here is sample HTML for the Font Family select from the Kitchensink example:
<label style="display: inline-block;" for="font-family">Font family:</label><select class="btn-object-action" id="font-family" bind-value-to="fontFamily">
<option value="arial">Arial</option>
<option value="helvetica" selected="">Helvetica</option>
<option value="myriad pro">Myriad Pro</option>
</select>
This is backed up by this in the controller:
function getActiveProp(name) {
var object = canvas.getActiveObject();
if (!object) return '';
return object[name] || '';
}
function setActiveProp(name, value) {
var object = canvas.getActiveObject();
if (!object) return;
object.set(name, value).setCoords();
canvas.renderAll();
}
$scope.getFontFamily = function () {
return getActiveProp('fontFamily').toLowerCase();
};
$scope.setFontFamily = function (value) {
setActiveProp('fontFamily', value.toLowerCase());
};
function watchCanvas($scope) {
function updateScope() {
$scope.$$phase || $scope.$digest();
canvas.renderAll();
}
canvas
.on('object:selected', updateScope)
.on('group:selected', updateScope)
.on('path:created', updateScope)
.on('selection:cleared', updateScope);
}
$scope.getSelected = function () {
return canvas.getActiveObject();
};
$scope.canvas = canvas;
$scope.getActiveStyle = getActiveStyle;
addAccessors($scope);
watchCanvas($scope);
I am more used to using ng-model than bind-value-to, in fact, I have never seen or used bind-value-to before in Angular apps/not sure how and if I should be using it.
My main question is how do I get the dropdowns working where if I select a value it updates per the Kitchensink example for text here? What I am missing/is there a better way given that my need is to add and edit stylized text.
You need to bind a change event to your select element so that when you change the select value, you execute the function that will change the font family.
bind-value-to is a custom directive in the kitchensink app so don't worry about it.
I'm setting the selection of my ngGrid from JavaScript, calling gridOptions.selectItem(). I have multiSelect set to false, so there is only ever one row selected. I'd like the ngGrid to automatically scroll to show the newly selected row, but I don't know how to do this: can anyone help, please?
On a related topic: can I disable row selection by mouse click? If so, how?
Edited to add
I'd also like to disable keyboard navigation of the selected row, if possible.
What worked:
AardVark71's answer worked. I discovered that ngGrid defines a property ngGrid on the gridOptions variable which holds a reference to the grid object itself. The necessary functions are exposed via properties of this object:
$scope.gridOptions.selectItem(itemNumber, true);
$scope.gridOptions.ngGrid.$viewport.scrollTop(Math.max(0, (itemNumber - 6))*$scope.gridOptions.ngGrid.config.rowHeight);
My grid is fixed at 13 rows high, and my logic attempts to make the selected row appear in the middle of the grid.
I'd still like to disable mouse & keyboard changes to the selection, if possible.
What also worked:
This is probably closer to the 'Angular Way' and achieves the same end:
// This $watch scrolls the ngGrid to show a newly-selected row as close to the middle row as possible
$scope.$watch('gridOptions.ngGrid.config.selectedItems', function (newValue, oldValue, scope) {
if (newValue != oldValue && newValue.length > 0) {
var rowIndex = scope.gridOptions.ngGrid.data.indexOf(newValue[0]);
scope.gridOptions.ngGrid.$viewport.scrollTop(Math.max(0, (rowIndex - 6))*scope.gridOptions.ngGrid.config.rowHeight);
}
}, true);
although the effect when a row is selected by clicking on it can be a bit disconcerting.
It sounds like you can make use of the scrollTop method for the scrolling.
See also http://github.com/angular-ui/ng-grid/issues/183 and the following plunker from #bryan-watts http://plnkr.co/edit/oyIlX9?p=preview
An example how this could work would be as follows:
function focusRow(rowToSelect) {
$scope.gridOptions.selectItem(rowToSelect, true);
var grid = $scope.gridOptions.ngGrid;
grid.$viewport.scrollTop(grid.rowMap[rowToSelect] * grid.config.rowHeight);
}
edit:
For the second part of your question "disabling the mouse and keyboard events of the selected rows" it might be best to start a new Question. Sounds like you want to set your enableRowSelection dynamically to false? No idea if that's possible.
I believe I was looking for the same behavior from ng-grid as yourself. The following function added to your gridOptions object will both disallow selection via the arrow keys (but allow it if shift or ctrl is held down) and scroll the window when moving down the list using the arrow keys so that the currently selected row is always visible:
beforeSelectionChange: function(rowItem, event){
if(!event.ctrlKey && !event.shiftKey && event.type != 'click'){
var grid = $scope.gridOptions.ngGrid;
grid.$viewport.scrollTop(rowItem.offsetTop - (grid.config.rowHeight * 2));
angular.forEach($scope.myData, function(data, index){
$scope.gridOptions.selectRow(index, false);
});
}
return true;
},
edit: here is a plunkr:
http://plnkr.co/edit/xsY6W9u7meZsTJn4p1to?p=preview
Hope that helps!
I found the accepted answer above is not working with the latest version of ui-grid (v4.0.4 - 2017-04-04).
Here is the code I use:
$scope.gridApi.core.scrollTo(vm.gridOptions.data[indexToSelect]);
In gripOptions, you need to register the gridApi in onRegisterApi.
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
},
var grid = $scope.gridOptions.ngGrid;
var aggRowOffsetTop = 0;
var containerHeight = $(".gridStyle").height() - 40;
angular.forEach(grid.rowFactory.parsedData, function(row) {
if(row.entity.isAggRow) {
aggRowOffsetTop = row.offsetTop;
}
if(row.entity.id == $scope.selectedId) {
if((row.offsetTop - aggRowOffsetTop) < containerHeight) {
grid.$viewport.scrollTop(aggRowOffsetTop);
} else {
grid.$viewport.scrollTop(row.offsetTop);
}
}
});