I have two different angular apps. I have to open a view of 'app_2' using iframe in 'app_1'. I also need to post some data from 'app_1' to 'app_2'.
How to achieve this in angularJS?
Thanks in advance. #SOS
I would use consider using postMessage...
In Angular terms this would mean that one app would send messages and the other one would be listening to messages.
So on the App that sits within the iframe you can make a factory that does the following:
/**
* App that sits within iframe:
*
* Inject this factory into your controller and call
* iFrame.messageParentIframe({hello: 'world'}) to send messages
* to the parent iFrame
*/
angular
.module('app')
.factory('iFrameMessenger', function($window) {
return {
messageParentIframe: function(message) {
$window.parent.postMessage(message, '*');
}
};
});
On the parent iFrame your code should look something like this:
/**
* App that is on parent iframe:
*
* Just using a controller for the sake of simplicity,
* but you could also use a Factory that only receives
* messages from iFrames and handle them according to each
* action, etc. You can get creative here on how you want
* to handle it.
*/
angular
.module('app')
.controller('AppCtrl', function($window) {
$window.addEventListener('message', function() {
// handle messages received from iframe
});
});
Related
I am working on app where I have 2 subdirectories inside public namely admin and core. admin is for admin users where we need to login and add,Edit,delete posts while in core we have pages which a public user or visitors can see. Now what I want is that I have a CRUD functionality implement in admin. I have controller, routes and services. but what I don't know is that how can I display the data in core views for public users I needs steps to to re-use some of the code from admin and retrieve and display data in core views.
Here is a link to the directory structure: http://take.ms/LdaWk
Imagine the following structure...
app
|- admin
|- api
|- core
The api defines your CRUD functions. For example, in Slim PHP something like
$api = new \Slim\Slim();
// audio/video
$api->get('/av', 'getAVs');
$api->get('/av/:id', 'getAV');
$api->post('/add/av', 'addAV');
$api->put('/update/av/:id', 'updateAV');
$api->delete('/delete/av/:id', 'deleteAV');
// define functions that handle http requests above...
Now in admin, you can call the api in angularjs using $http. For example calling the resource POST /add/av
var admin = angular.module('adminApp', ['ngRoute']);
admin.controller('addAvCtrl', function($scope, $http, MsgService){
MsgService.set('');
// process the form
$scope.submit = function() {
$http.post('../api/add/av', $scope.formData)
.success(function() {
MsgService.set('Success!');
});
};
$scope.message = MsgService.get();
});
In core you can use the same api to display data. For example calling the resource GET /av/:id
var core= angular.module('coreApp', ['ngRoute']);
core.controller('mediaCtrl', function($scope, $http, $routeParams){
$http.get('../api/av/' + $routeParams.id)
.success(function(response) {
$scope.media_detail = response;
});
});
Obviously, this is a rough outline. You would need to fill out the code, but it displays the principle.
You can implement a component base structure, something like:
Components
TestComponent
AddTestComoonent
EditTestComponent
ListTestComponent
That each component has own module and router. and whenever you want you can just inject the module and use it
I am working on Ionic Framework and there is a requirement that I need to inject the angular services in controller to get the data or perform any CRUD operation in backend. Please Let me know how I can do this?
if you are using Ionic2 here is an example on how to inject a Service into a controller; note the #Injectable decorator in the Service, the [providers] parameter of the #Page decorator in the Controller, and how the service instance is a parameter of the constructor.
Ionic Framework is build upon angular.js, so there s no difference in doing this in Ionic.
Its simple like
var myapp = angular.module('myApp',['ionic']);
myapp.service('MyService',['$http', function($http) {
return {
doSomeThing: function() {
// do something here with $http or whatever
},
doSomeThingElse: function() {
}
}
]);
myapp.controller('MyController',['MyService',function(MyService) {
MyService.doSomeThing();
}]);
In addition to the answer provided by #mJunaidSalaat,
You need to inject IONIC module to angular app module
The remaining implementation will be as it is in Angular
As per below, you can:
angular.module('myApp', ['ionic'])
According to the below image:
I want to improve components communication method....I think this way is not efficient.
When clicking tabsetComponent to emit event, then parent controller catch this event, changing rootScope variable. Using $watch rootScope variable in tableComponent to trigger http fetch data function...
Could anyone has better and efficient way to communicate sibling component?
The accepted AngularJS method for communication between components is using component attributes for communication.
<div ng-controller="rootCtrl as vm">
<tab-set-component tsc-click="vm.fn($event, data)">
</tab-set-component>
<table-component="vm.tableData">
</table-component>
</div>
For more information on defining component attributes, see AngularJS Comprehensive Directive API -- isolate scope
Best practices
Only use .$broadcast(), .$emit() and .$on() for atomic events
Events that are relevant globally across the entire app (such as a user authenticating or the app closing). If you want events specific to modules, services or widgets you should consider Services, Directive Controllers, or 3rd Party Libs
$scope.$watch() should replace the need for events
Injecting services and calling methods directly is also useful for direct communication
Directives are able to directly communicate with each other through directive-controllers
-- AngularJS Wiki Best Practices
Controller Example
In your html, you use vm.fn that came from root controller right? So your advice is it should call the click method defined root controller, the click method will trigger http request function defined on the rootScope, then get table component datas, then bind the datas on table component attribute.
As example:
angular.module("myApp", []);
angular.module("myApp").controller("rootCtrl", function($http) {
var vm = this;
vm.tableData = { /* initial data */ };
//click handler
vm.fn = function(event, url) {
$http.get(url).then (function onFulfilled(response) {
vm.tableData = response.data;
}).catch (function onRejected(response) {
console.log(response.status);
});
};
});
The above example avoids cluttering $rootScope. All the business logic and data is contained in the controller.
The controller sets the initial data for the table-component, receives click events from the tab-set-component, makes HTTP requests, handles errors, and updates the data to the table-component.
UPDATE -- Using Expression Binding
Another approach is using expression binding to communicate events:
<header-component view="root.view" on-view-change="root.view = $event.view">
</header-component>
<main-component view="root.view"></main-component>
For more information, see SO: How to pass data between sibling components in angular, not using $scope
With version 1.5.3, AngularJS added the $onChanges life-cycle hook to the $compile service.
app.component("mainComponent", {
template: "<p>{{$ctrl.count}}",
bindings: {view: '<'},
controller: function() {
this.count = 0;
this.$onChanges = function(changesObj) {
if (changesObj.view) {
this.count++;
console.log(changesObj.view.currentValue);
console.log(changesObj.view.previousValue);
console.log(changes)bj.view.isFirstChanged());
};
};
}
});
For more information, see AngularJS Comprehensive Directive API Reference -- Life-cycle hooks
See also SO: AngularJs 1.5 - Component does not support Watchers, what is the work around?
I am making an app and I was wondering what is a better way to approach this. I want to use Laravel as the backend, and AngularJS as the frontend.
Should I then leave the entire rendering and View completely to AngularJS and only use Laravel through AJAX calls? Or should I still load the basics from Laravel, and use AngularJS to enhance the experience?
Yes. You could use Laravel as RESTFul API and consume from client without using blade (so if you want it)
Here example:
class PostController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
return Post::orderBy('created_at', 'desc');
}
}
service in angular: ( I use Restangular lib, but you can use $http)
app.factory("PostsService", function(Restangular) {
return {
/*
* GET /posts -> Trae todos los posts
*/
all: function() {
return Restangular.all('posts').getList();
}
}
});
controller angular:
app.controller('HomeController', function($scope, PostsService){
PostsService.all().then(function(posts){
$scope.posts = posts.data;
});
});
i have some application settings that i want to retrieve from backend, so that they would be available to all of my application controllers via injection. What is the most angular-way to do that?
1) If i only needed settings for one or few controllers i could retrieve them via routing resolve method, but what about global application scope?
2) I could use the .run() method, but since call will be async i have no guaranties that my config will be loaded before i access controllers.
Currently my settings are returned as a json object, and my templates/html files are simply served by web server. So i cannot embed anything into script tags, parse html on the server side or any similar technique.
I would create a service for your settings. Then using the .run() method, called a service that returns your app settings data:
angular
.module('YourApp',[])
.service('Settings',function(){
this.data = {}
})
.run(function(Settings,$http){
$http
.get('/ajax/app/settings')
.success(function(data){
Settings.data = data
})
})
function Controller($scope,Settings){
// use your Settings.data
}
http://docs.angularjs.org/api/angular.Module#methods_run
There is a neat plugin to do the job. https://github.com/philippd/angular-deferred-bootstrap
You need to change bootstrap method
deferredBootstrapper.bootstrap({
element: document.body,
module: 'MyApp',
resolve: {
APP_CONFIG: function ($http) {
return $http.get('/api/demo-config');
}
}
});
angular.module('MyApp', [])
.config(function (APP_CONFIG) {
console.log(APP_CONFIG);
});