Trigger preview mode by passing data from one controller to another - html

I want to trigger a preview mode from one controller onto another using angular service but can't get the final step done. I am trying to get the url from the passed parameter into that ng-src in SideMenuCtrl. Not sure how to do it so that it would happen dynamically.
I have seen a few similar threads but not with a final end result like mine because I am trying to eventually display an image on the screen.
How would I link the passed parameter advert to vm.previewImage/.
var app = angular.module('app', [])
.service('appState', function() {
this.data = {
preview: {
enabled: false,
advert: ''
}
};
this.previewAdvert = function(advert) {
//flick the inPreview variable
this.data.preview = {
enabled: !this.data.preview.enabled,
advert: advert
}
}
})
.controller('SideMenuCtrl', function(appState) {
var vm = this;
vm.preview = appState.data.preview;
})
.controller('ContentCtrl', function(appState) {
var vm = this;
vm.advertUrl = 'http://1.bp.blogspot.com/-vXmHgrrk4ic/UpTbgBkp8eI/AAAAAAAAFjQ/ajBQ9WvwNUc/s1600/gloomy-stripes-dark-background-tile.jpg';
vm.previewAdvert = function() {
console.log('preview/stop preview');
appState.previewAdvert(vm.advertUrl);
}
});
<html ng-app="app">
<body>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<div ng-controller="SideMenuCtrl as vm">
<div class="ads" ng-if="vm.preview.enabled">
<img ng-src="{{vm.previewImage}}">
</div>
</div>
<div ng-controller="ContentCtrl as vm">
<label for="adInput">Advert URL</label>
<input type="url" id="adInput" ng-model="vm.advertUrl"></input>
<button ng-mouseenter="vm.previewAdvert()" ng-mouseleave="vm.previewAdvert()">Preview</button>
</div>
</body>
</html>

Your service is shared all right between your controllers. However I noticed that with AngularJs properties from the controller are not always updated when their value change.
When this happens, you can use a function that returns your value and use the function call instead your value in your views. This way, updates are detected.
(NOTE: I moved the "SideMenuCtrl" div under because with the image appearing, the button was not hovered anymore, causing "mouseleave" to be called and that produced a flickering)
var app = angular.module('app', [])
.service('appState', function() {
this.data = {
preview: {
enabled: false,
advert: ''
}
};
this.previewAdvert = function(advert) {
//flick the inPreview variable
this.data.preview = {
enabled: !this.data.preview.enabled,
advert: advert
}
}
})
.controller('SideMenuCtrl', function(appState) {
var vm = this;
vm.getPreviewImage = function(){
return appState.data.preview.advert;
};
vm.isPreviewEnabled = function(){
return appState.data.preview.enabled;
};
})
.controller('ContentCtrl', function(appState) {
var vm = this;
vm.advertUrl = 'http://1.bp.blogspot.com/-vXmHgrrk4ic/UpTbgBkp8eI/AAAAAAAAFjQ/ajBQ9WvwNUc/s1600/gloomy-stripes-dark-background-tile.jpg';
vm.previewAdvert = function() {
console.log('preview/stop preview');
appState.previewAdvert(vm.advertUrl);
}
});
<html ng-app="app">
<body>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<div ng-controller="ContentCtrl as vm">
<label for="adInput">Advert URL</label>
<input type="url" id="adInput" ng-model="vm.advertUrl"></input>
<button ng-mouseenter="vm.previewAdvert()" ng-mouseleave="vm.previewAdvert()">Preview</button>
</div>
<div ng-controller="SideMenuCtrl as vm">
<div class="ads" ng-if="vm.isPreviewEnabled()">
<img ng-src="{{vm.getPreviewImage()}}">
</div>
</div>
</body>
</html>

Related

AngularJS, how to display contents of a received JSON object

I have successfully received the JSON object from an API, which is evident from a console.log code. Now, I want to display the various elements in that JSON file. For example, the JSON contains elements like "name" and "url". How do I display these individually, in an h1 HTML element, after clicking the submit button and fetching the JSON file. I'm a newbie and sorry if this is an obvious question, I'm kinda stuck and need help. Thank you in advance!
My HTML Code is:
<body ng-app="myApp">
<div ng-controller="UserCtrl">
Search : <input type="text" placeholder="Search Employees"
ng-model="formData.searchText"/> <br/><br/>
<button ng-click="getByID()">Submit</button>
{{response.data.name}}
</body>
The JS is:
var myApp = angular.module('myApp', []);
myApp.controller('UserCtrl', function($scope, $http) {
var id = "my secret key comes here";
$scope.formData = {};
$scope.searchText;
$scope.getByID = function() {
$http.get("https://rest.bandsintown.com/artists/" + $scope.formData.searchText + "?app_id="+id)
.then(response => {
console.log(response.data.name)
})
}
});
Thank you so much in advance!
You need to use a variable to assign it with the response data and then use it in html. For example to display name from response.data.name:
<body ng-app="myApp">
<div ng-controller="UserCtrl as vm">
Search : <input type="text" placeholder="Search Employees"
ng-model="vm.searchText"/> <br/><br/>
<button ng-click="vm.getByID()">Submit</button>
<h1>{{ vm.name }}</h1>
</body>
In controller:
var myApp = angular.module('myApp', []);
myApp.controller('UserCtrl', function($http) {
let vm = this;
var id = "my secret key comes here";
vm.searchText;
vm.name;
vm.getByID = function() {
$http.get("https://rest.bandsintown.com/artists/" + vm.searchText + "?app_id="+id)
.then(response => {
console.log(response.data.name);
vm.name = response.data.name;
})
}
});
Put the data on $scope:
$scope.getByID = function() {
var url = "https://rest.bandsintown.com/artists/" + $scope.formData.searchText;
var params = { app_id: id };
var config = { params: params };
$http.get(url, config)
.then(response => {
console.log(response.data.name)
$scope.data = response.data;
})
}
Then use the ng-repeat directive:
<body ng-app="myApp">
<div ng-controller="UserCtrl">
Search : <input type="text" placeholder="Search Employees"
ng-model="formData.searchText"/> <br/><br/>
<button ng-click="getByID()">Submit</button>
{{data.name}}<br>
<div ng-repeat="(key, value) in data">
{{key}}: {{value}}
</div>
</div>
</body>
For more information, see
AngularJS ng-repeat Directive API Reference

Pass VueJS data key-variable to onmouseover atrribute inside a <a> tag

I have the following bits:
<script>
window.onload = function vue () {
var app = new Vue({
el: '#app',
data () {
return {
message: 'Click here to edit your details!'
}
}
});
}
</script>
<h2>Hello <a id="myName" href="#" onmouseover="???" v-bind:title="message">{{username}}</a></h2>
({{username}} is being fetched from a Django view.)
What I need is to pass the 'message' value to onmouseover somehow, or something similar, so that when you hover over the username link, it shows the value of message in a Vue tooltip.
Many Thanks
You can use v-on mouseover to fire a function wich will set the message :
window.onload = function vue () {
var app = new Vue({
el: '#app',
data () {
return {
message: '',
username: 'sss'
}
},
methods: {
showMessage() {
this.message= 'Click here to edit your details!'
}
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="app">
<h2>Hello <a id="myName" href="#" v-on:mouseover="showMessage" v-bind:title="message">{{username}}</a></h2>
<div>
{{message}}
</div>
</div>
I have just discovered that the VueJs data variable containing the "message" needs to be v-bind to an actual HTML element, as is, for example, an html tag's 'title' attribute. Thus, it can be passed to 's title attribute likewise:
<div id="app">
<a id="user_name" href="#" v-bind:title="message">{{user_name}}</a>
</div>
And having only this:
var app = new Vue({
el: '#app',
data: {
message: 'LOL'
}
})
And that's pretty much how it works, without a need for a mouseover call.

How do I communicate between sibling controllers?

Here's my code:
<div ng-controller="mainCtrl">
<button ng-click="onclick()"></button>
<button ng-click="onclick()"></button>
<button ng-click="onclick()"></button>
{{display}}
</div>
<div ng-controller="SecondController">{{display}}</div>
<div ng-controller="lastController">{{display}}</div>
I have to get some message in each div when the user clicks on the button.
I've tried the below code:
app.controller('mainCtrl',function($scope,$rootScope){
$scope.OnClick = function (msg) {
$rootScope.$broadcast("firstEvent",{});
}
$scope.$on("firstEvent", function (msg ) {
$scope.display = "hello world";
});
});
app.controller('SecondController',function( $scope){
$scope.$on("firstEvent", function (msg) {
$scope.display = "hello how Are you";
});
});
app.controller('lastController',function($scope) {
$scope.$on("firstEvent", function (msg) {
$scope.display = "this is my Query";
});
});
When the user clicks on each button, it should get data in each div.
How come its only possible with $on, $event and $broadcast?
$broadcast() sends an even downwards from parent to child controllers. The $emit() method, on the other hand, does exactly opposite. It sends an event upwards from the current controller to all of its parent controllers.
This is a simple example of communicating between controllers
angular.module("app", [])
.controller("mainCtrl", [
"$scope", "$rootScope",
function($scope, $rootScope) {
$scope.go = function(msg) {
if (msg == 1) {
$scope.display = "hello firstEvent";
} else if (msg == 2) {
$rootScope.$broadcast("showSomething", {});
} else {
$rootScope.$broadcast("showGoodBye", {});
}
};
}
]).controller("SecondController", [
"$scope", "$rootScope",
function($scope, $rootScope) {
$scope.$on("showSomething", function(msg) {
$scope.display = "hello Something";
});
}
]).controller("ThirdController", [
"$scope", "$rootScope",
function($scope, $rootScope) {
$scope.$on("showGoodBye", function(msg) {
$scope.display = "hello GoodBye";
});
}
]);
<div ng-app="app">
<div ng-controller="mainCtrl">
mainCtrl : {{display}}
<br>
<button ng-click="go(1)"> Show Hello </button>
<button ng-click="go(2)"> Show Something </button>
<button ng-click="go(3)"> Show GoodBye </button>
</div>
<hr>
<div ng-controller="SecondController">
SecondController : {{display}}
<hr>
</div>
<div ng-controller="ThirdController">
SecondController : {{display}}
<hr>
</div>
</div>
A complete Tour
Here is the solution:
I prefer not to use rootScope, you can use intermaeidate service to share data between two controllers
Solution with services:
Here is how service looks:
app.service('StoreService',function(){
var data;
this.save=function(data){
this.data=data;
};
this.getData=function(){
return this.data;
};
});
Using a service without rootScope
Demo without rootScope
Solution with rootScope
var app = angular.module('myApp', []);
app.controller('mainCtrl',function($scope,$rootScope){
$scope.buttonclick = function (msg) {
var object = {
data: msg
}
$rootScope.$broadcast("firstEvent",object);
}
$rootScope.$on("firstEvent", function (event, msg) {
$scope.display = msg.data;
});
})
app.controller('SecondController',function( $scope, $rootScope){
$rootScope.$on("firstEvent", function (event, msg) {
$scope.display = msg.data;
});
})
app.controller('lastController',function( $scope, $rootScope){
$rootScope.$on("firstEvent", function (event, msg) {
$scope.display = msg.data;
});
})
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp">
<div ng-controller="mainCtrl">
<button ng-click="buttonclick('button1')">button1</button>
<button ng-click="buttonclick('button2')">button2</button>
<button ng-click="buttonclick('button3')">button3</button>
<br>
{{display}}
</div>
<div ng-controller="SecondController">{{display}}</div>
<div ng-controller="lastController">{{display}}</div>
</div>
</body>
</html>
Please run the above snippet
Here is a Working DEMO

"[object object]" shown when double-clicking input

Below is the template I am using for the directive. In code we are
fetching the data from a service in that data we have all the
information of that particular person. And from that data we are
showing only first name, last name and designtion or company
affiliation.
<div ng-if="model" class="entry-added">
<span class="form-control"><b>{{model.fullName}}</b>, <br/><span class="small-font">{{(model.designation)?model.designation:model.companyAffiliation}}</span></span>
<a ng-click="removePerson()" class="action-remove"><i class="fa fa-remove"></i></a>
</div>
<div ng-show="!model" class="input-group">
<input type="text"
class="form-control"
name="{{name}}"
id="{{name}}"
placeholder="{{placeholder}}"
ng-required="{{isRequired}}"
typeahead-on-select = "change($item, $model, $label)"
ng-model="model"
typeahead-min-length="3",
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
typeahead-template-url="typeAheadTemplate.html"
typeahead-loading="searching"
typeahead-editable="false">
<script type="text/ng-template" id="typeAheadTemplate.html">
<a class="ui-corner-all dropdown" tabindex="-1">
<div class="col-md-2"><img class="dropdown-image" ng-src="https://people.***.com/Photos?empno={{match.model.employeeNumber}}"></div>
<div>
<div bind-html-unsafe="match.model.fullName"></div>
<div bind-html-unsafe="match.model.designation"></div>
</div>
</a>
</script>
I am using a custom directive to display a search field. The drop down is displaying [object object].
Directive
// In backend taxDeptContact is a Person type object
/*
Directive code
*/
(function () {
'use strict';
angular.module('treasuryApp.directives').directive('employeeSearch', employeeSearch);
employeeSearch.$inject = ['$resource', '$rootScope', 'ErrorHandler'];
function employeeSearch($resource, $rootScope, ErrorHandler) {
return {
restrict: 'E',
require: '^form',
scope: {
model: "=",
isRequired: '#',
submitted: "=",
onSelect: '&',
name: '#',
index:'#'
},
link: function(scope, el, attrs, formCtrl) {
//set required attribute for dynamically changing validations
scope.searchEmployees = function (searchTerm) {
var users = [];
var myResult = [];
var result = $resource($rootScope.REST_URL + "/user/getEmployees", {term: searchTerm}).query().$promise.then(function (value) {
//console.log(value)
$.each(value, function(i, o) {
users.push(o);
});
return users;
});
return result;
}
scope.removePerson = function() {
scope.model=null;
}
scope.userNotSelectedFromTypeahead = function(name) {
if(undefined === formCtrl[name]) {
return false;
}
return formCtrl[name].$error.editable;
};
scope.change = function(item, model, label) {
scope.model = item
scope.onSelect(
{name: scope.name, person: scope.model});
},
templateUrl: 'app/components/common/directives/employee-search.tpl.html'
};
}
})();
View that is using the directive
<div class="form-group">
<label class="col-sm-3>Tax Dept Contact</label>
<div class="col-sm-4">
<employee-search model="reqCtrl.requestObj.taxDepartmentContact" name="taxDeptContact" is-required="false" submitted="reqCtrl.submitted"/>
</div>
</div>
Image of the error occuring
Looks like this may be your trouble spot
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
suggestion for suggestion is pulling the whole object. Have you tried displaying a particular attribute of suggestion?
For example: if you had a suggestion.name attribute you would write:
typeahead="suggestion.name for suggestion in searchEmployees($viewValue)"
Finally got the answer: I used autocomplete="off" in my directive and thats all
<input type="text" autocomplete="off" />

How to update a specific div with ajax and jquery

I'm working on site and it has a fram. think of the gmail frame. And much like the gmail app I want only the inner div to be updated when clicking links on the navbar. I've got it so the div changes, but it certainly does not give me the results I'm hoping for. this is a rough outline of what I have
<div id=container>
<div id=page>
... some child divs in here
</div></div>
Because the container has a fixed scroll bar I don't want it to change I want to only replace the page div. this is what I managed to come up with on the jquery side. I'm just a beginner so I don't really know what I'm doing but I'm trying to learn.
$(document).ready(function () {
$.ajaxSetup ({
cache: false
});
var ajax_load = "<img src='bin/pics/loading.gif' alt='loading…' width='32px' height='32px' style='top: 250px; left: 250px;' />";
var loadUrl = "bin/ajax/load.html";
$("#mybuton").click(function(){
$("#page").load(loadUrl);
location.hash = 'ajax';
});
});
the load html contains this
<link rel="stylesheet" type="text/css" href="bin/main.css" />
<div id="page">
<div id="child">
<h1> sometitle </h1>
</div>
</div>
Any suggestions?
Here's the Jquery ajax link http://api.jquery.com/jQuery.ajax/
Eg Code :
ajax_control = jQuery.ajax({
url: "target.php",
type: "POST",
data: {variable_name: variable_value}
});
ajax_control.always(function(){
$('#content').html(ajax_control.responseText);
});
By assigning the call to a variable ("ajax_control" in the above example), you can abort whenever you want, by using :
ajax_control.abort();
http://api.jquery.com/jQuery.post/
http://api.jquery.com/jQuery.get/
I don't like to answer with links, nor just text, so here is an example of how can you make a div/table or mostly any html container to change it's content.
If you're using MVC with Razor it'd look like this
TestView.cshtml
#using (Ajax.BeginForm("Test",
"TestController",
new AjaxOptions {
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "searchResults" }))
{
Search User by ID: <input type="text" name="id" />
<input type="submit" value="Search" />
}
<table id="searchResults">
</table>
TestController.cs
public class TestController : Controller
{
public PartialViewResult Test(int id)
{
var model = myDbContext.Users.Single(q => q.UserID == id);
return PartialView("_PartialViewTest", model);
}
}
_PartialViewTest.cshtml
#model IEnumerable<MyApp.Models.User>
<table id="searchResults">
<tr>
<th>Name</th>
<th>Email</th>
</tr>
#foreach(var item in Model) {
<tr>
<td>#item.Name</td>
<td>#item.Email</td>
</tr>
}
</table>
...and if you want to do it using classic ASP.NET, it'd be like this:
TestPage.aspx
<body>
<form id="form1" runat="server">
<div>
<button type="button" onclick='testCall()'>Test!</button>
<hr />
<div id="ajaxResult">
</div>
</div>
</form>
</body>
Scripts.js / TestPage.aspx
function testCall() {
$.ajax({
url: "TestHandler.ashx",
dataType: 'json',
success: callbackTestCall
});
};
function callbackTestCall(payload) {
document.getElementById("ajaxResult").innerHTML = payload;
};
TestHandler.ashx
public class TestHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
Random random = new Random();
string actualData = random.Next(2001).ToString();
context.Response.ContentType = "text/plain";
context.Response.CacheControl = "no-cache";
context.Response.Write(jss.Serialize(actualData));
}
public bool IsReusable
{
// Whether or not the instance can be used for another request
get { return true; }
}
}
If you need further information please, let me know.