Angular-froala is not updating the ng-model - javascript

HTML:
<textarea froala="froalaOptions" ng-model="froalaContent"></textarea>
Controller:
$scope.froalaContent = '';
$scope.froalaOptions = {
placeholderText: '<i class="fa fa-book placeholder-icon"></i> Share your story',
events: {
'froalaEditor.focus': function () {
angular.element('.feed .fr-toolbar').css('display', 'block');
},
'froalaEditor.blur': function () {
angular.element('.feed .fr-toolbar').css('display', 'none');
}
}
}
Order of JavaScript inclusions:
"vendor/jquery/jquery-1.11.1.js",
"vendor/angularjs/plugins/angular-froala-master/jquery-embedly.js",
"vendor/angularjs/plugins/angular-froala-master/froala-editor.js",
"vendor/angularjs/plugins/angular-froala-master/froala-sanitize.js",
"vendor/angularjs/plugins/angular-froala-master/angular-froala.js",
"vendor/angularjs/plugins/angular-froala-master/embedly.min.js",
"vendor/angularjs/plugins/angular-froala-master/video.min.js",
"vendor/angularjs/plugins/angular-froala-master/image.min.js",
"vendor/angularjs/plugins/angular-froala-master/lists.min.js",
"vendor/angularjs/plugins/angular-froala-master/image.min.js",
"vendor/angularjs/plugins/angular-froala-master/colors.min.js",
"vendor/angularjs/plugins/angular-froala-master/font_size.min.js",
"vendor/angularjs/plugins/angular-froala-master/font_family.min.js",
In the function ctrl.updateModelView() in angular-froala.js, I can see that the value is being updated correctly, but it just doesn't seem to pass the value back to the parent scope. No matter what I do, whenever I log the $scope of my controller, froalaContent is always equal to an empty string.
I somehow managed to get it to work earlier by changing the ng-model on the HTML element to ng-model="$parent.froalaContent" but that doesn't seem to be working anymore.
I've been studying the documents for a while now and I feel like I have everything in its proper place, can anyone share some insight as to where I've gone wrong? Could it be I'm using an out-of-date version of jQuery or did I mess up the order of file inclusions?
Thanks for any and all help.

Related

Vue and Summernote - content from model not showing in form when loaded from db

Ok, I have a form in which I am using the wysiwyg editor summernote several times. When I fill in my form, the model is updated correctly, the content is shown and the results are saved correctly to the database. BUT when I want to edit and load the data from the database, the model is showing the contents correctly in the developer tools, but nothing makes it on to the screen.
This is what I have:
I have a component to load and initiate the summernote editor
<template>
<textarea class="form-control"></textarea>
</template>
<script>
export default{
props : {
model: {
required: true
},
height: {
type: String,
default: '150'
}
},
mounted() {
let config = {
height: this.height,
};
let vm = this;
config.callbacks = {
onInit: function () {
$(vm.$el).summernote("code", vm.model);
},
onChange: function () {
vm.$emit('update:model', $(vm.$el).summernote('code'));
},
};
$(this.$el).summernote(config);
}
}
</script>
I have a form (here is only one part of it) where I load the Summernote component as html-editor:
<html-editor
:model.sync="form.areaOfWork"
:class="{ 'is-invalid': form.errors.has('areaOfWork') }"
name="areaOfWork"
id="areaOfWork"></html-editor>
In the props, after loading from the DB, the data shows correctly, i.e.:
model:"<p> ... my content ...</p>"
Likewise, in my form it shows correctly, i.e.:
form: Object
areaOfWork: "<p> ... my content ...</p>"
...
But it is not shown in html-editor. I am stuck - maybe it is something super simple I am overlooking, but I did not find anything that helped me so far. Thanks for ideas and inputs
I think the problem stemmed from using jquery and vue in one project!
Because vue uses virtual DOM and jquery changes the real DOM, this makes the conflict!
So it is better not to use both of them in one project or use jquery safe in it like link below:
https://vuejsdevelopers.com/2017/05/20/vue-js-safely-jquery-plugin/
Thanks for your answer, #soroush, but that doesn't seem to be the problem. There is a communication and it seems to work. I do see my form being filled with correct data as well.
After playing around with numerous ideas, I found a simple work-around: watcher
I added
watch: {
areaOfWork: (val) => {
$('#areaOfWork').summernote("code", val);
}
},
to my template and the according variables to my data().
When I call my database and read the item, I provide the data for the watcher and it works.
Still, I do not get why vm.model in the onInit callback is not shown, but as it seems to work, I wanted to provide you with an answer. Maybe it helps someone else
HTML:
<textarea class="summernote-editor"name="memo_content"id="memo_content"</textarea>
JS:
$('#memo_content').summernote("code", response.data.res.memo_content);

Angularjs: ng-class and CSS animations (running only once)

I am an AngularJS newbie so please be patient.
First, the code. Here's the relevant .html part:
<span ng-class="{'error-text': true, 'animated-error': vm.email_error}" ng-show="vm.email_error" translate>EMAIL_ERROR</span>
The .scss part:
.error-text{
position: absolute;
&.animated-error{
animation: bigandnormal 2s;
}
}
And there is a .js that is modifying vm.email_error after a click:
var validateEmail = function(){
var isEmailValid = /(.+)#(.+){2,}\.(.+){2,}/.test(vm.email);
vm.email_error = !isEmailValid;
return isEmailValid;
};
A button click runs the validateEmail() function.
What happens here is that when I perform the first click (with an invalid email) the class is added correctly to the span and the animation runs.
But if I click again, the animation is NOT run again.
Looking at the inspector, it seems that the class in never added again.
I have even tried to reset vm.email_error to false in the first line of the validateEmail() function and removed the animated-error from the console before clicking again:
angular.element(".error-text").each(function(index, el) {
angular.element(el).removeClass('animated-error');
});
But I cannot see anymore the animation and the class.
But in any case I do not think I am not doing it the right way, there should be a way to accomplish this.
This is what I am asking you :)
Thanks in advance.
UPDATE: I if put vm.email_error = !isEmailValid; in a setTimeout it works properly. It would be great to have an explanation from someone who knows that technology. Of course, it is clear that this cannot be the real solution.
Try to declare your email_error variable as a $scope or $rootScope variable rather than as a controller variable.
var validateEmail = function(){
var isEmailValid = /(.+)#(.+){2,}\.(.+){2,}/.test(vm.email);
$scope.email_error = !isEmailValid; // or $rootScope.email_error = !isEmailValid;
return isEmailValid;
};
And you don't need the quotes around your css class name.
Then call it in your html without prefixes, like this:
<span ng-class="{error-text: true, animated-error: email_error}" ng-show="email_error" translate='EMAIL_ERROR'></span>
Also, be careful on how to use angular translate :
If you use it as a directive, you have to write it as
<p translate='MY_TRAD'></p>
If you use it as a filter, then it's
<p>{{ 'MY_TRAD' | translate }}</p>
(angular translate doc: https://github.com/angular-translate/angular-translate)

How to replace a child view with another in AngularJS

I have an SPA written in AngularJS. The main page uses an ng-include attribute to determine which view to load. This is set in JavaScript when someone clicks on a menu which is contained within the main page. However, I've come across a situation where I need to load a different view by clicking a button within another view, essentially replacing it.
I'm trying to figure out how to do this and from what I've researched, I have to use $rootScope and either an $emit or $broadcast call in the child view and a $rootScope.$on method to detect this event.
The thing is, this doesn't seem to work. I have set my breakpoints and stepped through the code, but I always get this error:
Error: [ngModel:datefmt] http://errors.angularjs.org/1.5.7/ngModel/datefmt?p0=2009-07-21T00%3A00%3A00
Here's the code in my parent page controller:
$rootScope.$on('viewChanged', function () {
var menuItem = {
template: 'customerOrders.html' // will be eventually dynamic
};
navigate(menuItem);
});
function navigate(menuItem) {
$scope.activeMenuItem = menuItem;
}
<div data-ng-include="activeMenuItem.template"></div>
In the child page controller:
function changeSelectedView(viewTemplate) {
$rootScope.$emit('selectedViewChanged', viewTemplate);
}
Obviously I'm doing something wrong here. How do I accomplish what I want, or is there a completely different way to do this?
you can use ng-route to work between views. check https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
First of all, the event name in the $emit function and in the $on function did not match, so I made that fix.
function navigateToNewTemplate(event, viewTemplate) {
var menuItem = {
template: buildTemplateUrl(viewTemplate)
};
navigate(menuItem);
}
$rootScope.$on('selectedViewChanged', navigateToNewTemplate);
function changeSelectedView(viewTemplate) {
$rootScope.$emit('selectedViewChanged', viewTemplate);
}

Confirmation dialog with data using AngularJS

I am trying to make a dialog box that confirms the user wants to proceed.
The situation is this: I have a table with may events. The user can decide to delete the event.
The table is built like this:
<tbody>
<tr ng-repeat="event in EventsCtrl.events>
<td>
<a ng-click="event.updateStatusDone(event.eventid)" href="#">
<i class="delete-icon"></i>
</a>
</td>
<td>{{event.timestamp}}</td>
<td>{{event.date}}</td>
...
The relevant code in the controller looks like this:
app.controller('EventController', ['$http', function($http){
this.updateStatusDone = function(eventid){
$http.delete(serverUrl + "/manage/event/" + eventid);
}
}
Now I'd like to add a confirmation box (I read about modal), that will ask the user to confirm.
The eventid has to be passed through.
I've tried researching a lot about modal, but they all seem to alert, without passing the data required (eventid in this case).
Does anyone have a working example? A lead, some reference to give?
Thanks in advance!
Here is a partial example to get you started, from something I wrote:
function createMessageBox($dialog, title, message, buttons) {
var msgBox = $dialog.dialog({
templateUrl: 'partials/dialogs/message_dialog.html',
controller: 'MessageBoxController',
backdrop: false,
dialogClass: 'modal confirm-dialog movable',
resolve: {
model: function () {
return {
title: title,
message: message,
buttons: buttons
};
}
}
});
return msgBox;
}
As you can see I'm passing the title, message and buttons variables, and later using them in the message_dialog.html dialog.
I found the best thing so far to fit my situation here:
https://stackoverflow.com/a/19930247/5459561
It actually calls my function only if accepted.
One thing to keep in mind, it is not a good looking dialog box, that part still needs work.

Angular: Run method every time a directive updates

I'm looking to have a function run every time an angular directive updates. In my case, I have an array of modal configurations that get used on a modal markup template.
Every time the template is used to generate a modal due to a change in the model, I want to run a positionModal() method.
scope.$watch in the link function doesn't seem to notice when I change the model, and I cant think of any other way of doing this. I tried a post-link function thinking that the compile function would get called when the directive was applied, but that doesn't seem to work either. Here is my example controller:
MyApp.controller("ModalController", function () {
//Define scope vars
$scope.modals = [];
$scope.$on("modalTrigger", function (event, settings) {
$scope.modals.push(settings);
});
});
Note: I've simplified the controller here- know that it DOES work.
Here is the template code:
<div class="modalParent" ng-controller="ModalController">
<div id="{{modal.id}}" class="modal" ng-class="modal.type" ng-repeat="modal in modals">
<div class="content">
<h2 ng-show="modal.title">{{modal.title}}</h2>
<p>{{modal.message}}</p>
<button>{{modal.button}}</button>
</div>
</div>
</div>
The directive is currently like this:
MyApp.directive("modalParent", function () {
var positionModals = function (element) {
element.find(".modal .content").each(function () {
//position logic here
});
};
return {
restrict: "C",
compile: function (tElement) {
positionModals(tElement);
}
};
});
Note: Also simplified for the purposes here.
The positionModals() call works when the first modal gets pushed to the array. After that, it stops working.
I've tried using the linking function as well, same result. scope.$watch(modals, function(){...}) does not work.
Can somebody help me figure out what I'm doing wrong?
Figured it out!
I was applying the directive to the parent, ".modalParent".
The ng-repeated element in this case is the modal itself ".modal".
You would want the directive to run on elements that get updates as the model changes, because then the linking function will get called each time the element is instantiated, rather than sitting and watching the parent and trying to update from there.
Hope this helps somebody.
Instead of calling like this, my approach is to write this in the services and inject that services in the controller wherever you want to get that function or the data to be notified as,
Services.js
as.service("xyzservice",function(factoryname){
//here the code goes...
})
Now inject in Controller,
ac.controller("controllername",function(xyzservice){
})
ac.controller("controllername",function(servicename){
})
ac.controller("controllername",function(xyzservice){
})
Here we have injected it in the two controller, we can get it.

Categories

Resources