Two way binding for angular strap - angularjs

I'm fairly new to angularjs and am using angular strap to use some of their features like aside.
So basically I have a function like this:
$scope.myAside = function() {
$aside({
title: 'My Title',
show: true,
animation: 'am-slide-left',
placement:'left',
contentTemplate: 'views/aside.html'
});
};
and I wanted to know how to use the two binding to get 'show' to display on the page. I basically wanted something like this on the page:
The aside is open: {{myAside.show}}
I read through their setup but couldn't find anything about two binding and how to know if the aside modal is open or not.
Here is the plugin with the documentation about aside. http://mgcrea.github.io/angular-strap/#/asides

You need to use {{ myAside.$scope.$isShown }}
Here is a plnkr showing how this works.

Related

Use the same template on different scopes

I have a ui-grid that allows users to select a row:
angular.module("app").component("mycomponent", {
templateUrl: "View.html",
controllerAs: "m",
controller: [Interactor_Controller]
})
function Interactor_Controller() {
var m = this
m.gridOptions = {enableRowSelection: true, enableRowHeaderSelection: false}
m.gridOptions.columnDefs = [
{field: "id"},
{field: "name"}
]
m.gridOptions.multiSelect = false
m.gridOptions.onRegisterApi = function(gridApi){
m.infoGridApi = gridApi
gridApi.selection.on.rowSelectionChanged(null, function(row){
m.infoGridSelectedRow = row.entity
})
}
$http
.get('lottastuff')
.success(response => {
m.gridOptions.data = response
m.gridApi.selection.selectRow(m.gridOptions.data[0]);
m.gridSelectedRow = m.gridApi.selection.getSelectedRows()
})
}
The template would be just a ui-grid invocation:
<div class="gridStyle" ui-grid="m.gridOptions" ui-grid-selection></div>
I'd like to be able to do something like this:
<div class="container-fluid">
<div class="xs-col-12">
<myReusableGrid>
</div>
</div>
(Where the scope is implied because the component is using that page as it's template).
This works when it's built inside a controller, but I need to
Reuse in multiple views
Get data from the controller
Send the selected row to the controller and the view it's being inserted into.
What should I use to accomplish this? Directive? Factory? Template? Something else? I'm not exactly sure how to do most of that, but I want to make sure I'm on the right track before I spend time figuring it out (time is essential).
How do I send data from the controller?
How do I send data to the controller?
I recommend you use a Component.
In AngularJS, a Component is a special kind of directive that uses a
simpler configuration which is suitable for a component-based
application structure.
This makes it easier to write an app in a way that's similar to using
Web Components or using the new Angular's style of application
architecture.
Source: https://docs.angularjs.org/guide/component
I really like components because is write a controller for a specific part of your view, instead of a state.
Also, take the components path in angularjs, will make easier to you learn Angular (aka angular2).
This tutorial help me a lot: https://tests4geeks.com/build-angular-1-5-component-angularjs-tutorial/

Angular UI Grid callbacks not received

I'm trying to get a callback from the Angular UI grid (after data is loaded/rendered) but it doesn't seem to work for me.
I'm following this which says I should listen the scope using $scope.$on() and I tried this which implies I can provide a dataUpdated() and init() delegate through the options.
In both cases I don't see anything in my console... The grid renders fine and I can also see a console entry stating: 'grid refresh'.
I'm loading the grid with the following options:
$scope.$on('ngGridEventRows', function (event) {
console.log('rendering');
});
$scope.$on('ngGridEventRows', function (event) {
console.log('rendering');
});
$scope.options = {
enableSorting: true,
//data: myData,
dataUpdated: function() {
console.log('dataUpdated');
},
init: function () {
console.log('init');
}
};
$scope.grids = [$scope.options];
The options are passed to the grid as follows:
<div class="container-fluid" ng-repeat="grid in grids">
<div ui-grid="grid" ui-grid-exporter></div>
</div>
Those events are related to ng-grid (probably version 2.x) while you are using ui-grid (which is a rename of ng-grid version 3.0).
I'd suggest you to give a look at the updated website ui-grid.info where you can find docs and tutorials about the current version.
Regarding your peculiar need sadly it seems there is no documented event you can use, but looking through the code I found the following:
$scope.grid.api.core.on.rowsRendered( $scope, function() );
You should put this in your gridOptions.onRegisterApi(...) and the function will be called upon rendering is complete (or so it seems looking at the source).
I'd suggest you to play a bit with it and see what it can do.

AngularJS ui-grid issue with directive in cellTemplate

I have hit a head scratcher! It seems like a fairly simple issue... I am using the ui-grid angular control and I'm attempting to use a custom directive in the cellTemplate. I can succesfully get it in there, but the problem is I am not able to bind correctly to the directive. I can bind properties but not functions from the parent. When I try to access a parent function which has been bound I get an object not defined error.
As far as I know I setup binding and cell template correctly:
//in columndefs:
{
name: 'item', displayName: 'Status',
width: 200, cellTemplate: '<dropdowncss item="row.entity[col.field]" do-drop="dropdowncombo"></dropdowncss>'
},
//directive declaration:
app.directive('dropdowncss', function () {
return {
restrict: 'E',
scope:
{
item: '=',
doDrop: '&'
},
controller: 'DropDownCSSCtrl',
templateUrl: 'dropdowncss.html'
};
When you click on one of the colored drop downs it should alert 'success'
Please see the simple plunker here:
http://plnkr.co/edit/HuuxxgV1GoWzfWlUvafw?p=preview
Any help would be appreciated. Thanks!
So from the scope that the cellTemplate gets compiled, you are many miles deep in scopes and your function dropdowncombo does not exist. That is why you get undefined. From that scope, Your dropdowncombo function is actually $parent.$parent.$parent.$parent.$parent.$parent.dropdowncombo. Now I would never suggest you use that so you should engineer an alternate way to pass you scoped function from that cell template.
To view your plunker working, change line 20 of app.js to
width: 200, cellTemplate: '<dropdowncss item="row.entity[col.field]" do-drop="$parent.$parent.$parent.$parent.$parent.$parent.dropdowncombo"></dropdowncss>'
I would make the edit for you, but it's just too embarrassing to have that many $parents even in this modern age of acceptance.
So there are a few ways to fix this but here's my take. Save the function from your scope that you want to execute in the column definition and then call that using col.colDef.func
Updated column definition in app.js is as follows:
{
name: 'item', displayName: 'Status',
handleClick: $scope.dropdowncombo,
width: 200,
cellTemplate: '<dropdowncss item="row.entity[col.field]" do-drop="col.colDef.handleClick"></dropdowncss>'
}
Here's an edited working plunker
This question is Old but I have a better approach -
you can use grid.appScope to access current $scope.
so change you line 20 in app.js to -
width: 200, cellTemplate: '<dropdowncss item="row.entity[col.field]" do-drop="grid.appScope.dropdowncombo"></dropdowncss>'
working Plunker is here -
http://plnkr.co/edit/5LiETuG2PEOJhvEcFypF?p=preview
In case anyone else was curious I also found the method using events. $emit can be used to broadcast an event up the whole parent scope hierarchy. So the following worked:
Adding this to the parent scope:
$scope.$on('EventDropDown', function () {
alert('passed up the event successfully');
});
And calling it from the directive like this:
<div class="divDropDown" ng-click="$emit('EventDropDown')">
That passed it up to the parent scope correctly. In contrast to $emit, $broadcast sends events down the scope hierarchy (not applicable in this scenario). There is no other hooking up things other than the event name. That makes it kind of convenient.

Using ACE editor with Angular - splitting the value by newline

I am using the ace-ui directive with angular to use the ACE code editor in my application. It works great so far, but I am having one little caveat.
I need code that is written to get stored as an array of strings, separated by the \n character. This is easy to do at first, I just do this;
In the controller, I have a $scope.$watch on the actual editor text, it looks like this;
app.controller("EditorCtrl", [ "$scope", function($scope){
$scope.Model = {
// other properties
Scripting: ""
};
$scope.Editor = {
// other properties
Scripting: ""
};
$scope.aceLoaded = function(editor){
ace.require("ace/ext/language_tools");
// setup the defaults
editor.setTheme("ace/theme/chrome");
editor.getSession().setMode("ace/mode/javascript");
// options
editor.setOptions({
showGutter: true,
showPrintMargin: false,
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: '14px',
fontFamily: 'Consolas'
});
}
$scope.$watch("Editor.Scripting", function(n, o){
$scope.Model.Scripting = n.split("\n");
});
});
This seems to work fine, but I don't think it is right to have Scripting twice. Is there a simpler way to accomplish this that will not require $watch or will not require having to proxy it through a second variable on the $scope? I've tried binding to $scope.Model.Scripting directly, but that caused some strange behavior when it came to loading an object that already had scripting on it.
The HTML for this looks like ..
<div ui-ace="{ onLoad: aceLoaded }" data-ng-model="Editor.Scripting"></div>
{{ Model.Scripting }}
You do not describe why do you need this, but if you are not going to modify that array, and you always want the latest version, you could use internal lines array used by ace editor.session.doc.$lines, which would be faster as it won't need to create new array on every change.

Fotorama: how should I initialize Fotorama that is created dynamically?

I wish to use Fotorama in my project. But my project uses AngularJS to load the partial view which contains
<div class="fotorama">
<img src="1.jpg"><img src="2.jpg"><img src="3.jpg">
</div>
But that cannot initialize fotorama since the html is loaded via AJAX.
How should I load Fotorama under this situation?
The problem is I think similar to handling event on element created dynamically. For instance,
<div class="myImg">Some Img</div>
And you write,
$('.myImg').on('click', function() {
alert('Clicked');
});
The alert won't fire if the div is created dynamically. But the following would work:
$(document).on('click', '.myImg', function() {
alert('Clicked');
});
I think the same case is true for fotorama. So how should I do similar thing for the case of Fotorama?
Thank you very much.
You may check official documentation: http://fotorama.io/customize/api/
Or use one of angular wrappers: https://github.com/tamtakoe/ap.fotorama
Probably, you have to parse images from HTML chunk, or redesign it all (sending HTML by AJAX isn't good approach) to send JSON. Something like this:
$('.fotorama').fotorama({
data: [
{img: '1.jpg', thumb: '1-thumb.jpg'},
{img: '2.jpg', thumb: '2-thumb.jpg'}
]
});
Or like this (will modify existing fotorama instance):
fotorama.load([
{img: '1.jpg', thumb: '1-thumb.jpg'},
{img: '2.jpg', thumb: '2-thumb.jpg'}
]);
PS
If you going to create DOM element dynamically, you should add event listeners after it been added to document. for example
$.get({/* url, etc */})
.success(plainHtml) {
$('el').append(plainHtml)
$('selector').on('click', onClickCallback)
})
Also, you can manually initialize fotorama on the DOM element: $('.fotorama').fotorama(). In onSuccess callback, of course. Actually, you shouldn't use jQuery in AngularJs projects.

Resources