AngularJS - Switch between Templates - php

Currently, I have my directives being switched out in this fashion.
In my directive:
(function(){
'use strict';
var controller = ['$scope', function ($scope) {
}];
angular
.module('moduleName', ['myDependency'])
.directive('dirName', function($compile, $window){
return{
restrict: 'E',
replace: true,
require: [ '^?myDependency'],
scope: false,
controller: controller ,
template:
`<div ng-switch="templateConfig.type">
<div ng-switch-when='con1'>
<p> Config 1 </p>
</div>
<div ng-switch-when='con2'>
<p> Config 2 </p>
</div>
<div ng-switch-when='con3'>
<p> Config 3 </p>
</div>
</div>`
And in the PHP file, I have the following:
function pageController($scope, $http, $filter, $cleo, $timeout, $compile) {
$scope.templateConfig= {type: 'Con2'};
}
<div class="row-fluid">
<div class="span1" id="title" > name </div>
<div class="span11">
<dirName>
</dirName>
<br/>
</div>
</div>
<div class="row-fluid">
<div class="span1" id="title" > name2 </div>
<div class="span11">
<dirName>
</dirName>
<br/>
</div>
</div>
So how it works is that when I can switch between templates using {type: 'Con2'}. However, this will affect both <dirName></dirName> tags. What I want is for me to have the ability to define them independently of each other.
What I want would be something like <dirName templateConfig=Con1></dirName>. I not entirely sure how to achieve this though but I don't think it should be too difficult to make the switch.
Also, I did leave out a lot of code from the PHP file and changed the original names in the code but none of that should be relevant.

Use the function form of the template property:
app.directive('dirName', function($compile, $window){
return{
restrict: 'E',
template: function (elem, attrs) {
switch(attrs.templateConfig) {
case 'con1':
return `<p> Config 1 </p>`;
case 'con2':
return `<p> Config 2 </p>`;
case 'con3':
return `<p> Config 3 </p>`;
};
}
};
})
Example usage:
<dir-name template-config="con2">
</dir-name>
Update
From the Docs:
template
Value may be:
A function which takes two arguments tElement and tAttrs (described in the compile function api below) and returns a string value.
— AngularJS Comprehensive Directive API Reference - template

Related

Vue2 Laravel component in list

I am building a Laravel app and trying to use vue.js (without much success!). I'm not understanding the way components work with ajax data. Almost all examples I've found showing this functionality define the data for the component at the app level, not the component level.
I'm trying to dynamically define my data in the component itself, and always get the error that Property or method tasks is not defined on the instance but referenced during render. Here's the component, which is meant to just call out to an endpoint to pull basic "to do" tasks:
Vue.component('tasks', {
data: function() {
return {
tasks: []
}
},
mounted() {
this.getTasks();
},
methods: {
getTasks() {
axios.get('/tasks').then(function (response) {
this.tasks = response.data;
console.dir(this.tasks);
})
.catch(function (error) {
console.log(error);
});
}
},
template: `
<div class="card">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
`
});
the component is called from within the blade template using:
<tasks v-for="task in tasks" :key="task.id"></tasks>
tasks is declared in the data function, so I'm not sure why vue is telling me it's not defined?
When you define a data property on a component it's only available within that component and its template. Your v-for directive is in the parent scope (i.e outside of the component where tasks is defined).
The simplest solution here is probably to move the container element inside the component, and iterate over the tasks there:
<div>
<div class="card" v-for="task in tasks" :key="task.id">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
</div>
Note: you can't use v-for a template's root element, which is why you'd move the container element into the template.
An alternative is break this into two components (e.g. TaskList and TaskItem) where the parent component is responsible for fetching the tasks from the API. The child component can just receive a single task as a prop and render it to the UI.
TaskList
Vue.component('task-list', {
data: function() {
return {
tasks: []
}
},
mounted() {
this.getTasks();
},
methods: {
getTasks() {
axios.get('/tasks').then(response => {
this.tasks = response.data;
console.dir(this.tasks);
})
.catch(error => {
console.log(error);
});
}
},
template: `
<div class="container">
<task-item
v-for="task in tasks"
:key="task.id"
:task="task"
/>
</div>
`
});
TaskItem
Vue.component('tasks', {
props: {
task: {
required: true
}
},
template: `
<div class="card">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
`
});
The advantage of this is that it separates the responsibility of the components a little better. You could add logic to the TaskList component to handle displaying a loading spinner and/or error messages for the API call, while TaskItem only has to concern itself with displaying a single task.

Ajax Based Select2 Codeigniter Issue

Hi friends I am trying to do a Ajax Based select2 using codeigntier. I am using 4.0.1 Select2 Version. I am getting the response from ajax but the result is not showing in SELECT2. Can you please check the code below and tell me where I have done wrong.
Here is my Model
//Model
class AddServiceAreaModel extends CI_Model
{
//Function for getting suburbs from restaurant
//MAIN FUNCTION FOR DATATABLE
public function get_postcodes($q)
{
$query = $this->db->select('postcode')
->group_by('postcode')
->like('postcode', $q)
->get('tbl_suburb');
$json = $query->result_array();
echo json_encode($json);
}
}
Here is my View
<div id="page-inner">
<div class="row">
<div class="col-md-12">
<!-- Advanced Tables -->
<div class="panel panel-default">
<div class="panel-heading"> Add Service Area</div>
<form id="addFrm">
<div class="panel-body">
<div class="">
<!-- Modal content-->
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="postcode">Postcode</label>
<select class="selectbox form-control required" id="postcode" name="postcode"></select>
</div>
</div>
</div>
</div>
<button type="submit" id="btnSubmit" class="btn btn-success">Update</button>
</div>
</form>
</div>
<!--End Advanced Tables -->
</div>
</div>
<!-- /. ROW -->
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#postcode').select2({
placeholder: 'Select for tag',
ajax: {
url: '<?php echo base_url('restaurant/addservicearea/get_postcode') ?>',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: data
};
},
cache: true
}
});
});
</script>
Here is My Controller
public function get_postcode()
{
//$_GET['term']. Term is the variable is in jquery-ui.js file.
if(isset($_GET['term']))
{
$q = $_GET['term'];
$this->AddServiceAreaModel->get_postcodes($q);
}
}
The output showing blank result even i got the response in ajax.
Can you please help me where i am wrong? Thanks in advance.
Earlier I thought you need a success function, but select2 uses the processResults function. It turns out, you just need that to look like this:
processResults: function (data) {
return {
results: data.items
};
},
Then, in PHP when you send back your response, select2 expects an items element, and then arrays that contain "id" and "text":
// This is just a sample, of course yours will be dynamic
echo json_encode(array(
'items' => array(
array('id' => '0', 'text' => '12345'),
array('id' => '1', 'text' => '12346'),
array('id' => '2', 'text' => '12347')
)
);
I tested this out locally, and I was getting results after making these changes. Should work for you now.

laravel 5.4 Vue Component not workng

I have a Chat-User.vue file in components like
<template lang="html">
<div class="chat-user">
×
<h1>Users in Chat Room</h1>
<hr />
Number of users = {{ usersInRoom.length }}
<div class="users" style="overflow: hidden;">
<div class="col-sm-3 w3-margin-bottom" v-for="userInRoom in usersInRoom" style="overflow: hidden;">
<div class="u-1">
<img :src="userInRoom.profile" width="50" height="50">
</div>
<div class="u-2">
{{ userInRoom.name }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['usersInRoom']
}
</script>
My app.js file
Vue.component('chat-user', require('./components/Chat-User.vue'));
const app = new Vue({
el: '#app',
data: {
usersInRoom: []
},
});
and the indx.blade.php file
<div id="app">
<chat-user v-bind:usersInRoom="usersInRoom"></chat-user>
</div>
In usersInRoom variable it will add data's automatically.
But when I look the browser I cannot see any thing in the place of <chat-user></chat-user>, Just only <!---->.
I think it was commented out by vue for some reason. I tried removing all {{ usersInRoom }} and then I can see the other things like <h1>Users in Chat Room</h1> and the <hr>.
if I am not wrong The component file is not recognizing any variable like usersInRoom, when I have a variable like that.
Please some one tell me how to fix this problem.
Html directives are case insensitive, in the documentation Vue mentions that you need to use kebab-case in binding props.
Try <chat-user v-bind:users-in-room="usersInRoom"></chat-user> Which will bind to the usersInRoom prop.
you cant use camel case for props. u need to to use kebab case.
and binding from vue 1, you can remove the "v-bind" string and just directly start at :
<chat-user :users-in-room="usersInRoom"></chat-user>

Multiple Jplayer audio players from Laravel DB

I'm trying to create multiple instances of Jplayers that each play a different audio file from my Laravel Database (table called archives) and i'm stuck at the point the jQuery code meets the Laravel code.
So far the audio players play but they play the same file.
also i have trouble when i navigate deeper into the website. ex: with mydomain.com/segments/ the audio player adds "segments" to the url instead of just the public directory. I know a similar issue can be solved with the URL:asset in Laravel, but i'm not sure how to with this since it's the jquery that's getting the file.
This is where i try to create my multiple jplayer instances using a laravel Forloop (i need to start at 2 because player 1 is being used elsewhere)I'm confused about how to mix the Laravel and Jquery code.
This is all in my footer.blade.php
<!--{{{$counter = 2}}}-->
#foreach ($archives as $archive)
<script>
var counter = "{{$counter}}";
var file = "archiveAudio/{{$archive->audioFile}}";
$(document).ready(function(){
$("#jquery_jplayer_"+ counter).jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
title: "Hidden",
mp3: file,
oga: ""
});
},
play: function() { // To avoid multiple jPlayers playing together.
$(this).jPlayer("pauseOthers");
},
swfPath: "../../js",
supplied: "mp3, oga",
cssSelectorAncestor: "#jp_container_" + counter,
wmode: "window",
globalVolume: true,
useStateClassSkin: true,
autoBlur: false,
smoothPlayBar: true,
keyEnabled: true
});
counter ++;
});
</script>
#endforeach
Home page Blade View (needs to start with #2 player add 1 to the player ID for each player it creates)
<div id="latest">
<!-- {{ $count = 2}} -->
#foreach ($archives as $archive)
<div class="singleLatest">
<img src = "/images/segments/{{$archive->segment->image}}" width="100px;"/>
<div class="playerAndInfo">
<h3> {{ $archive->archiveTitle}}<br>{{$archive->segment->name}}</h3>
<div id="jquery_jplayer_{{$count}}" class="jp-jplayer"></div>
<div id="jp_container_{{$count}}" class="jp-audio" role="application" aria-label="media player">
<div class="jp-type-single">
<div class="jp-gui jp-interface">
<div class="jp-controls">
<button class="jp-play" role="button" tabindex="0">play</button>
</div>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
<div class="jp-time-holder">
<div class="jp-current-time" role="timer" aria-label="time"> </div>
<div class="jp-duration" role="timer" aria-label="duration"> </div>
</div>
<div class="jp-no-solution">
<span>Update Required</span>
To play the media you will need to either update your browser to a recent version or update your Flash plugin.
</div>
</div>
</div>
</div>
</div><!--end playerAndInfo-->
</div> <!-- end single latest -->
<!-- {{ $count = $count +1}} -->
#endforeach
</div><!-- End latest -->
Thanks!

How to change the default setFlash () in CakePHP?

How to change the default setFlash () in CakePHP ?
How or where change this default element:
<div id="flashMessage" class="message">
My message.
</div>
Necessary:
<div id="myid" class="myclass">
My message.
</div>
Thanks.
According to the documentation:
Create the file app/View/Elements/flash_custom.ctp and build our custom flash element:
<div id="myid"><?php echo $message; ?></div>
Then call setFlash() with those parameters:
<?php
$this->Session->setFlash('My message.', 'default', array('class' => 'myclass'));
The output in your template from using $this->Session->flash() with the above example would be then:
<div id="myid" class="myclass">My message.</div>

Categories