how to appear the image in ember with handlebars - image

Hello I want to appear the image from code i wrote below but i cant. Any ideas?
I googled and i found that i must use a helper function.
(template)
showallapps.hbs
{{#if getappsexist}}
{{#each app in getapp}}
{{#each app.app_files}}
{{#link-to "dashboard" app}}
<img {{bind-attr src=get_url}} class="img-responsive">
{{/link-to}}
{{/each}}
{{#link-to "dashboard" app}}
{{app.app_name}}
{{/link-to}}
(controller)
showallapps.js
import Ember from 'ember';
export default Ember.ObjectController.extend({
apps:[],
getappsexist: function () {
var appsexist = false;
if (this.store.all('userapp').content.length > 0) {
appsexist = true;
}
return appsexist;
}.property(),
getapp: function () {
this.apps = this.store.all('userapp');
return this.apps;
}.property(),
get_url: function (){
var url = 'http://' + JSON.parse(this.apps.content[2]._data.app_files).url;
return url;
}.property()
});
I have this json.
{
"userapp": [
{
},
{
"app_files": "{"url":"static.xxx.xxx/data/application/3911efd9-413a-11e1-b5e9-fbed80c8f6ba/eleutheris_epilogis.jpg","mime":"image/jpeg","name":"eleutheris epilogis.jpg"}"
}
]
}
I get these errors:
Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed {"url":"static.xxx.xxx/data/application/3911efd9-413a-11e1-b5e9-fbed80c8f6ba/eleutheris_epilogis.jpg","mime":"image/jpeg","name":"eleutheris epilogis.jpg"}

You need to form the image url as a property of some type in your controller (as you did with the getUrl computed property). Then you can bind to that by doing something like this:
<img {{bind-attr src=getUrl}} class="img-responsive" />

Related

vue-18n - how to force reload in computed function when changing language

I am using vue-i18n but I also have some content which is stored in database. I would like my text to be updated when the user changes the language.
I am using laravel and vuejs2.
Thanks in advance, I am not super familiar with vuejs yet. I hope it's clear enough.
in ContenuComponent.vue
<template>
<div>
{{$i18n.locale}} <== this changes well
<div v-html="textcontent"></div>
<div v-html="textcontent($i18n.locale)"></div> <== this won't work, I am wondering how to put params here (more like a general quetsion)
</div>
</template>
<script>
export default {
name:'contenu',
props: {
content: {
type: String,
default: '<div></div>'
}
},
computed: {
textcontent: function () {
console.log(navigator.language); <== this gives me the language as well, so i could use it if I can make it reload
var parsed = JSON.parse(this.content);
parsed.forEach(element => {
if(navigator.language == element['lang']){
return element['text'];
}
});
}
}
}
</script>
in ContentController
public function getcontent(){
$content = DB::connection('mysql')->select( DB::connection('mysql')->raw("
SELECT text, lang from content
"));
return view('myvue', ['content' => json_encode($content)]);
}
in content.blade.php
<div id="app">
<contenu content="{{ $content }}"></contenu>
</div>
You SHOULD NOT pass parameters to computed props! They are not methods and you should create method instead:
methods: {
textcontent () {
var parsed = JSON.parse(this.content)
parsed.forEach(element => {
if (navigator.language == element['lang']){
return element['text']
}
})
}
}
Also you should consider ES6 syntax:
methods: {
textcontent () {
var parsed = JSON.parse(this.content)
const content = parsed.find(element => navigator.language == element['lang'])
return content['text']
}
}
Much cleaner!
Please make sure to read about computed props and how they are different than methods or watchers: docs

Search in vuejs with laravel backend api

I'm using laravel 5.6 as the api for the backend and vuejs for the frontend spa application. And https://github.com/nicolaslopezj/searchable package for search which worked well in my previous projects where i used blade templating engine.
I'm new to vuejs and im learning how to do things and im stuck at a point where im confused how to use laravel search on the frontend.
What i did previously in other projects where i used blade for the frontend
In my controller
public function index(Request $request)
{
$start_search = microtime('s');
$searchterm = $request->input('search');
if($request->has('search')){
$results = Web::search($searchterm)->paginate(10);
} else {
$results = Web::latest()->paginate(10);
}
$stop_search = microtime('s');
$time_search = ($stop_search - $start_search);
return view('search.index', compact('results', 'searchterm', 'time_search'));
}
And in my view
<small>{{$results->total()}} results found for "<em class="b-b b-warning">{{$searchterm}}</em>" in {{$time_search}} seconds</small>
#forelse ($results as $result)
<div class="mb-3">
{{$result->meta_title}} <span class="badge badge-pill primary">{{$result->rank}}</span>
<span class="text-success clear h-1x">{{$result->url}}</span>
<span class="h-2x">{{$result->meta_description}}</span>
</div>
#empty
No Results Found
#endforelse
<div class="pt-2 pagination-sm">
{{ $results->links('vendor.pagination.bootstrap-4') }}
</div>
This code worked well where i was able to search and display results properly along with search time.
Now i want to do the same with laravel api and vuejs frontend. So this is what i tried
public function index(Request $request)
{
$start_search = microtime('s');
$searchterm = $request->input('search');
if($request->has('search')){
$results = Web::search($searchterm)->paginate(10);
} else {
$results = Web::latest()->paginate(10);
}
$stop_search = microtime('s');
$time_search = ($stop_search - $start_search);
return WebResource::collection($results);
}
I created a collection resource for the same.
Question 1. My question related to controller code, how to return $searchterm and $time_search so that i can use them on the frontend.
In my vue component, i tried with my learning till now
<template>
other code..
<div class="mb-3" v-for="result in results" :key="result.results">
<router-link :to="result.url" class="text-primary clear h-1x"> {{ result.meta_title }} </router-link>
<span class="h-2x">{{ result.meta_description }}</span>
</div>
</template>
<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
export default {
layout: 'main',
computed: mapGetters({
locale: 'lang/locale',
authenticated: 'auth/check'
}),
metaInfo () {
return { title: this.$t('searchpagetitle') }
},
data: function () {
return {
results: [],
title: window.config.appName
}
},
watch: {
locale: function (newLocale, oldLocale) {
this.getResults()
}
},
mounted() {
console.log(this.locale)
this.getResults ()
},
methods: {
getResults() {
var app = this;
axios.get('/api/web')
.then(response => {
// JSON responses are automatically parsed.
this.results = response.data.data
})
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
Question 2: My second question related to vuejs, how to create a search form and render results according to the search and with proper search url ending with ?searchterm=searchkeywords in my case.
When i used blade i used the normal html form with action url so that it rendered results. Also i used $searchterm to use the same search terms to search in other routes like images, videos.
I just used {{ url('/images?searchterm='.$searchterm) }} in the href so that when user clicks on it, it renders results of all images with the same keyword just like google. And also used placeholder as "enter your search" and value as "{{$searchterm}}" so that the search term stayed in the search form too.
I want to know how to do all the same in vuejs.
Thank you
It is better to append the search keyword in request URL of API in frontend. So your request url will be like
axios.get('/api/web?searchterm='+this.searchterm)
And in your Laravel controller, you can get this value by using Input::get() , so your code to get searchterm will be
$searchterm = Input::get('searchterm');
And then you can fetch your data on basis of $searchterm variable.

Vue-Multiselect with Laravel 5.3

I'm new to Laravel and Vue and need help implementing Vue-Multiselect.
I don't know how to pass the actual options to the select.
My vue file:
<template>
<div class="dropdown">
<multiselect
:selected.sync="selected"
:show-labels="false"
:options="options"
:placeholder="placeholder"
:searchable="false"
:allow-empty="false"
:multiple="false"
key="name"
label="name"
></multiselect>
<label v-show="showLabel" for="multiselect"><span></span>Language</label>
</div>
</template>
<script>
import { Multiselect } from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
options: {},
placeholder: {
default: 'Select one'
},
showLabel: {
type: Boolean,
default: true
},
selected: ''
}
};
</script>
My blade file:
<div class="form-group">
<drop-down
:options="{{ $members->list }}"
:selected.sync="selected"
:show-label="false"
></drop-down>
</div>
In my controller method I tried a few things:
1.
public function edit($id)
{
....
$members_list = Member::orderBy('member_first_name')->pluck('member_first_name', member_id');
return view('businesses.edit', compact('members_list'));
}
I got this error:
[Vue warn]: Invalid prop: type check failed for prop "options". Expected Array, got Object. (found in component: ).
2.I tried:
$members = Member::orderBy('member_first_name')->pluck('member_first_name', member_id');
$members_list = $members->all();
return view('businesses.edit', compact('members_list'));
I got this error:
htmlspecialchars() expects parameter 1 to be string, array given (View: C:\wamp\www\ccf.local\resources\views\businesses\edit.blade.php)
3.
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = array();
foreach($members as $mem) {
$members_list[$mem->member_id] = $mem->member_first_name;
}
I got this error: htmlspecialchars() expects parameter 1 to be string, array given (View: C:\wamp\www\ccf.local\resources\views\businesses\edit.blade.php)
So I need help with 2 things:
How to send the $members_list as the options
How can I combine the member_first_name and member_last_name fields so I can get options like this:
option value="member_id"
option text = member_first_name member_last_name
Thank you
When using prop binding inside of laravel {{ }} tries to output an escaped form of the variable.
what you need is a javascript array. if $members_list returns a collection, which seems to be indicated by your other code, try
<drop-down
:options="{{ $members_list->toJson() }}"
:selected.sync="selected"
:show-label="false"
></drop-down>
as for your controller this will help
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = $members->map(
function($member) {
return [
"value" => $member->member_id,
"label" => $member->member_first_name. " ". $member->member_last_name
];
}
);
Laravel Collections have a good selection of function that help to manipulate data will map your members array to the structure of { value: "", label: "" } when you convert to Json.
Lastly don't forget to set up your prop bindings in vue.
props: {
options: {
type: Array,
default: function() {
return [];
}
},...
}
That should get you going.

Having trouble updating a scope more than once

I'm using angular with the ionic framework beta 1.
Here's my ng-repeat html:
<a href="{{item.url}}" class="item item-avatar" ng-repeat="item in restocks | reverse" ng-if="!$first">
<img src="https://server/sup-images/mobile/{{item.id}}.jpg">
<h2>{{item.name}}</h2>
<p>{{item.colors}}</p>
</a>
</div>
And here's my controllers.js, which fetches the data for the ng-repeat from a XHR.
angular.module('restocks', ['ionic'])
.service('APIservice', function($http) {
var kAPI = {};
API.Restocks = function() {
return $http({
method: 'GET',
url: 'https://myurl/api/restocks.php'
});
}
return restockAPI;
})
.filter('reverse', function() {
//converts json to JS array and reverses it
return function(input) {
var out = [];
for(i in input){
out.push(input[i]);
}
return out.reverse();
}
})
.controller('itemController', function($scope, APIservice) {
$scope.restocks = [];
$scope.sortorder = 'time';
$scope.doRefresh = function() {
$('#refresh').removeClass('ion-refresh');
$('#refresh').addClass('ion-refreshing');
restockAPIservice.Restocks().success(function (response) {
//Dig into the responde to get the relevant data
$scope.restocks = response;
$('#refresh').removeClass('ion-refreshing');
$('#refresh').addClass('ion-refresh');
});
}
$scope.doRefresh();
});
The data loads fine but I wish to implement a refresh button in my app that reloads the external json and updates the ng-repeat. When I call $scope.doRefresh(); more than once, I get this error in my JS console:
TypeError: Cannot call method 'querySelectorAll' of undefined
at cancelChildAnimations (http://localhost:8000/js/ionic.bundle.js:29151:22)
at Object.leave (http://localhost:8000/js/ionic.bundle.js:28716:11)
at ngRepeatAction (http://localhost:8000/js/ionic.bundle.js:26873:24)
at Object.$watchCollectionAction [as fn] (http://localhost:8000/js/ionic.bundle.js:19197:11)
at Scope.$digest (http://localhost:8000/js/ionic.bundle.js:19300:29)
at Scope.$apply (http://localhost:8000/js/ionic.bundle.js:19553:24)
at done (http://localhost:8000/js/ionic.bundle.js:15311:45)
at completeRequest (http://localhost:8000/js/ionic.bundle.js:15512:7)
at XMLHttpRequest.xhr.onreadystatechange (http://localhost:8000/js/ionic.bundle.js:15455:11) ionic.bundle.js:16905
It looks like it's related to a bug, as per:
https://github.com/driftyco/ionic/issues/727
Which was referenced from:
http://forum.ionicframework.com/t/show-hide-ionic-tab-based-on-angular-variable-cause-error-in-background/1563/9
I'm guessing it's pretty much the same issue.
Maybe try instead using angular.element(document.getElementById('refresh')) for a possible workaround (guessing).

Bootstrap Typeahead with AJAX source (not working)

I'm trying to implement a search bar dropdown using bootstrap v3.0.0 with typeahead.js.
My search bar will take a student's firstname and lastname. I'm using a MYSQL database which consists of a table called practice with afirstname, alastname, aid as columns. The search bar should not only contain the firstname and lastname in the dropdown, but also the id associated with it in a second row. I've read all the examples on the typeahead.js page and I'm unable to do it with ajax call.
Below is the code of my index.php
JS
<script type="text/javascript">
$(document).ready(function() {
$('.cr.typeahead').typeahead({
source: header: '<h3>Select</h3>',
name: 'accounts',
source: function (query, process) {
return $.getJSON(
'localhost/resultly/source.php',
{ query: query },
function (data) {
return process(data);
});
});
});
</script>
HTML:
<body>
<div class="container">
<br/><br/>
<input type="text" name="query" class="form-control cr typeahead" id="firstname" />
<br/><br/>
</div>
</body>
Code for source.php : This should return the firstname and lastname from my database in the form of a json string or object?
<?php
$query = $_POST['query'];
try {
$conn = new PDO('mysql:host=localhost;dbname=practice','root','');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT * FROM actualtable WHERE afirstname LIKE '%($query)%'");
$stmt->execute();
}
catch (PDOException $e) {
echo 'ERROR:' . $e->getMessage();
}
foreach ($stmt as $row) {
$afirstname[] = $row['afirstname'];
$alastname[] = $row['alastname'];
}
echo json_encode($afirstname);
echo json_encode($alastname);
?>
result:
http://oi41.tinypic.com/50moi1.jpg
Nothing shows up. I've tried adding a prefetch:
prefetch: {
url: 'localhost/resultly/source.php',
filter: function(data) {
r1 = [];
for (var i = 0; i < data.length; i++) {
r1.push({
value: data[i].afirstname,
tokens: [data[i].afirstname, data[i]alastname],
afirstname: data[i].afirstname,
alastname: data[i].alastname,
template: '<p>{{afirstname}} - {{alastname}}</p>',
});
}
return r1;
}
}
Please do provide a solution or an example which I could refer.
Update:
The source.php should return a list of json encoded data. I debugged by looking at the output that the source.pho created. What I did wrong was whenever I was supposed to put a url I did localhost/source.php instead of just source.php.
Solution provided by Bass Jobsen works and now I have run into another problem.
I'm using
if(isset($_POST['query']))
{ $q_uery = $_POST['query'];
$query = ucfirst(strtolower($q_uery))};
to take the user's data and use it for searching logic
$stmt = $conn->prepare("SELECT * FROM actualtable WHERE afirstname LIKE '%($query)%'");
The updated source.php is http://pastebin.com/T9Q4m10g
I get an error on this line saying Notice: Undefined variable: stmt I guess the $query is not being initialized. How do I get this to work. Thanks.
Update 3
I used prefetch: instead of 'remote:' that did all the matching.
Your return is not correct:
echo json_encode($afirstname);
echo json_encode($alastname);
See for example Twitter TypeAhead.js not updating input
Try echo json_encode((object)$stmt);, see: typeahead.js search from beginng
Update
I tried echo json_encode((object)$stmt);still doesn't work.
Do you use any kind of debugging? What does? source.php return? Try to follow the steps from
typeahead.js search from beginng without the filter.
html:
<div class="demo">
<input class="typeahead" value="" type="text" spellcheck="off" autocomplete="off" placeholder="countries">
</div>
javascript:
$('.typeahead').typeahead({
remote: 'http://testdrive/source.php?q=%QUERY',
limit: 10
});
php (source.php):
<?php
$people = array();
$people[] = array("lastname"=>"Inaw",
"firstname"=>"Dsajhjkdsa");
$people[] = array("lastname"=>"Dsahjk",
"firstname"=>"YYYsgbm");
$people[] = array("lastname"=>"Dasjhdsjka",
"firstname"=>"JHJKGJ");
$datums = array();
foreach($people as $human)
{
$datums[]=(object)array('value'=>$human['firstname'],'tokens'=>array($human['firstname'],$human['lastname']));
}
echo json_encode((object)$datums);
This should work
update2
Thanks, it worked. How do I display 2 or more 'value'?
add some values to your datums in source.php:
foreach($people as $human)
{
$datums[]=(object)array
(
'value'=>$human['firstname'],
'tokens'=>array($human['firstname'],$human['lastname']),
'firstname'=>$human['firstname'],
'lastname'=>$human['lastname']
);
}
firstname and lastname now are field you csn use in your templates
Add a template and template engine to your javascript declaration:
$('.typeahead').typeahead({
remote: 'http://testdrive/source.php?q=%QUERY',
limit: 10,
template: [
'<p>{{firstname}} - {{lastname}}</p>'
].join(''),
engine: Hogan
});
The above make use of https://github.com/twitter/hogan.js. You will have to include the template engine by javascript, for example:
<script src="http://twitter.github.io/typeahead.js/js/hogan-2.0.0.js"></script>
It is working for me. please follow below step.
Please add below Js and give proper reference.
bootstrap3-typeahead
--- Ajax Call ----
$("#cityId").keyup(function () {
var al = $(this).val();
$('#cityId').typeahead({
source: function (valuequery, process) {
var states = [];
return $.ajax({
url: http://localhost:4000/GetcityList,
type: 'POST',
data: { valueType: "", valueFilter: valuequery },
dataType: 'JSON',
success: function (result) {
var resultList = result.map(function (item) {
states.push({
"name": item.Value,
"value": item.Key
});
});
return process(states);
}
});
},
});
});
---- Cs Code ---
public JsonResult SearchKeyValuesByValue(string valueType, string valueFilter)
{
List<KeyValueType> returnValue = SearchKeyValuesByValue(valueType, valueFilter);
return Json(returnValue);
}
Auto suggest of Bootstrap typehead will get accept only "name" and "value" so create reponse accordinly

Resources