I have multiple states in my page that change the following element :
<header ng-view></header>
I decieded to add animation to the page's transition so and decided to go with ng.animate + animate.css. so I added the following class to the header :
.slideInLeft.ng-enter
{
transition-animation: slideInLeft 1s ease-in-out;
}
.slideOutRight.ng-leave
{
transition-animation: slideOutRight 1s ease-in-out;
}
and changed my header to this :
<header ng-view class='slideInLeft slideOutRight'></header>
This works quite well but the problem comes when I want to change my animations on the run. Since the user can go to the next page or the previous page so the class should change from 'slideInLeft slideOutRight' to 'slideOutLeft slideInRight'
I tried changing the class attribute directly but the new element (the one which is entering) stayed with the same classes as before.
I tried using ng-class='someVar' and giving 'someVar' the names of the classes but that didn't work either, I'm guessing angular didn't have a chance to update the UI since I changed the properites of 'someVar' right before using $state.go to the new page.
Someone has done it before/has an ideas how to solve this?
I managed to do it using :
<header ng-view ng-class="getAnimation()"></header>
By putting a function in the ng-class attribute, I could just make it return a scope variable. That scope variable is changed right before I go to the next page/previous page.
$scope.getAnimation = funtion()
{
return $scope.classVar;
}
$scope.nextClick = function()
{
$scope.classVar = "slideInLeft slideOutRight";
}
$scope.prevClick = function()
{
$scope.classVar = "slideOutLeft slideInRight";
}
Related
I am working with angularjs 1.6, leaflet and mapbox. I am trying to recreate a box whose value changes based on which polygon you are hovering over in an angularjs way. The behaviour I want to recreate is in this example
http://leafletjs.com/examples/choropleth/
You can see the value in the box in the top right of the map changes based on which polygon you are hovering over. When I try to recreate it in an angular way, the view does not update but I can see the value in my component updating.
html:
<div class="data">{{vm.polygonValue}}</div>
Controller (same as the highlight feature in the example):
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 3,
color: '#666',
fillOpacity: 0.5
});
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
addValue(layer.feature.properties);
}
function addValue(props){
vm.polygonValue = props.value;
}
All runs in the controller and I can see the vm.polygonValue change when you hover over a polygon but the view doesn't change. Can someone help? Wondering is it because the value changes too frequently or something and angular cant handle it?
Probably your function is triggered outside of the angular digest cycle, to notify angular about changes you need to execute it within $scope.$apply function.
Something like $scope.$apply(() => addValue(layer.feature.properties)) should work. You can find out more about $apply in the docs: https://code.angularjs.org/1.6.9/docs/api/ng/type/$rootScope.Scope#$apply
I have defined kendo tooltip in following way:
<i class="fa fa-info-circle ico-tooltip" kendo-tooltip k-content="model.Description"></i>
Initially the content is ok, but when model.Description is changed and the site is not reloaded the k-content shows the old value.
After reload site by F5 there is new value, but this is not what I want to achieve.
It is possible to somehow refresh this tooltip or workaround this issue?
I had a similar issue and I debugged through Kendo's code and following solution works, in my case I wanted to show only upto 22 characters of text from my model and show full text in the tooltip, here is example code
This sample below is using Angular's 1.5 component
<div kendo-tooltip="$ctrl.selectedItemTooltip" k-content="$ctrl.selectedItemText">{{$ctrl.selectedItemText | limitTo:22}}</div>
and in JS
function fetchFromServer(){
$http.get('/myService').then(function(response){
ctrl.selectedItemText = response.data.model.text;
ctrl.selectedItemTooltip.options.content = ctrl.selectedItemText
ctrl.selectedItemTooltip.refresh();
});
}
in the tooltip options object (when you initialize the tooltip) you set function for the hide event (check documentation ) and in this function you could call refresh function
`
var tooltip = $("#container").kendoTooltip({
hide: function() {
tooltip.refresh();
}
})
`
i think this will do the trick
In my app, I am getting the show method issue. something is wrongly going on with my app. But i couldn't able to find that.
in case if i do like this my view is properly rendering ( but this is wrong approach ):
regions:{
header:'header',
content:'section',
footer:'footer'
},
initialize:function(){
console.log('initialized by layout')
},
renderRegions:function(options){
this.formData = _.defaults(options || {}, requireViews);
if(this.formData.headerView){ //this is true.
this.headerView();
this.renderHeaderView();
}
},
headerView:function(){
this.appHeaderView = new AppHeaderView({model:this.model});
return this.appHeaderView;
},
renderHeaderView:function(){
$(this.header.el).html(this.appHeaderView.render().el) //working fine
//but this is not workig: this.header.show(this.appHeaderView)..why not working?
}
why i use the "this.header.show" - nothing is appending to header.
Any one highlight me what is wrong i do here?
I have simplified my total process, and added in Jsfiddle here is the link:
Live Demo Here
You have a few issues in your code:
A view's model needs to be instantiated, not just the model class.
There is absolutely no reason for you to overwrite the ItemView's render method with what you had.
Your order of operations is wrong. show can only be called after the Layout is in the DOM already.
Here's the main thing that fixes your issue:
var Controller = Backbone.Marionette.Controller.extend({
initialize:function(){
this.layout = new Layout;
$('#wrapper').html(this.layout.render().el);
this.layout.renderRegions();
}
});
Updated FIDDLE
Another option (and something I find myself doing often) is to render the regions using the onShow method of the layout.
I want to render some Ext components into the output of an XTemplate. We want to have the flexibility of using an XTemplate to render the HTML but retain the styling, behaviour, and handlers of using Ext components rather than plain old HTML elements.
I am currently successfully doing this with an Ext.Button. In the template I am writing a placeholder div like so:
<div id="paceholder-1"></div>
After I have called apply() on the template I then create a new Ext component and render it in like so:
this._replacePlaceholders.defer(1, this, [html, 'placeholder-1', collection]);
The _replacePlaceholders function looks like this:
_replacePlaceholders: function(html, id, collection) {
var emailField = new Ext.form.TextField({
emptyText: 'Email address',
hideLabel: true
});
var downloadButton = new Ext.Button({
text: 'Download as...',
icon: 'images/down.png',
scope: this,
menu: this._createDownloadOptionsMenu(collection) // Create Menu for this Button (works fine)
});
var form = new Ext.form.FormPanel({
items: [emailField, downloadButton]
});
downloadButton.render(html, id);
}
This works and renders the button into the html correctly. The button menu behaves as expected.
But if I change the last line of replacePlaceholders to emailField.render(html, id); or form.render(html, id); I get a javascript error.
TypeError: ct is null
ct.dom.insertBefore(this.el.dom, position);
ext-all-debug.js (line 10978)
I'm a bit confused because from what I can tell from the docs the render() method called is going to be the same one (from Ext.Component). But I've had a bit of a play around and can't seem to track down what is happening here.
So is there any good reason why these components behave differently from Ext.Button? and is it possible to render an Ext.form.TextField or an Ext.form.FormPanel or anything that will let me use an Ext text field in mt XTemplate html?
NB. I am using ExtJS 3.3.1 and don't have the opportunity to upgrade the version. I believe ExtJS 4 has functionality which would make doing what I doing much easier.
Thanks!
Solution is quite simple - use form.render(id) instead of form.render(html, id).
See [api][1] if you have doubts.
The reason why button is rendering properly is that it has weird onRender implementation, different from Component.
onRender : function(ct, position){
[...]
if(position){
btn = this.template.insertBefore(position, targs, true);
}else{
btn = this.template.append(ct, targs, true);
}
[...]
}
As you can see in code above, if you provide position (which is basically second argument provided to render) it doen't use ct (which is first argument passed to render).
In normal component onRender method looks like this:
onRender : function(ct, position){
[...]
if(this.el){
this.el = Ext.get(this.el);
if(this.allowDomMove !== false){
ct.dom.insertBefore(this.el.dom, position);
if (div) {
Ext.removeNode(div);
div = null;
}
}
}
}
In code above, you can see, that ct is called always, despite the position is not null.
The bottom line is that rendering of button works by accident.
The Problem:
I have an anchor tag with a class name 'hasChildren' which in turn has a span element containing the text. When using EXT's .on('mouseenter',function()) on the anchor tag, it fires the event on both the span and/or the anchor tag.
expected result:
hovering over either the span or the anchor tag, the class should be added to the anchor tag alone
current result:
hovering over either the span or the anchor tag, the class is added to the element which receives focus first.
As in the JS you'll see I tried the hover function but gives the same results.
The HTML:
<a class="hasChildren" href="#"><span>web 2.0</span></a>
The CSS:
.hasChildren {
display:block;
width:100px;
background-color:#333;
}
.hasChildren span {
background-color:#EEE;
display:block;
line-height:40px;
margin-left:10px;
padding:0 20px 10px 10px;
}
The JavaScript:
function over(e,t){
Ext.get(t).addClass('red');
}
function out(e,t){
Ext.get(t).removeClass('red');
}
Ext.onReady(function() {
//Ext.select('.hasChildren').hover(over,out,this);
Ext.select('.hasChildren').on('mouseenter',over);
Ext.select('.hasChildren').on('mouseleave',out);
});
FYI: I'm using ext-core-3.1.0 and I can get this working by using jQuery but as the lead developer requested that I only use extJS, I'd like to get this working without adding another javascript library.
Use this function of Ext.Element : addClassOnOver(). So, for your case, it will be:
Ext.onReady(function() {
Ext.select('.hasChildren').addClassOnOver('red');
});
It will automatically toggle the CSS class.
Try and surround your anchor tag in a div and then attach the listeners on the div. I think you want to try and attach the events to the outermost container in this case.
I eventually found what I was looking for. The javascript functions should change to look like this:
function over(e,t){
Ext.get(e.getTarget('a')).addClass('red');
}
function out(e,t){
Ext.get(e.getTarget('a')).removeClass('red');
}
The explanation: Previously I tried to add the class to 't' as in get(t), which rightfully could be either the parent or child element. But by using (e.getTarget('a')) I tell it to select the anchor tag and apply the class to that element alone.
This method gives one control over propagation, funny thing is the following could also work for the 'out' function and it would do exactly the same (in theory):
function out(e,t){
Ext.get(e.getTarget('span')).parent().removeClass('red');
}
Another thing I discovered: The Ext.onReady functions can also be written as:
Ext.select('.hasChildren').on( { mouseenter: { fn: over } } );
This way makes it easier to add more events to the target element(s)
Ext.select('.hasChildren').on( { mouseenter: { fn: over } }, { mouseleave: { fn: out } });